home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / emacs.lha / emacs-19.16 / lisp / cplus-md1.el < prev    next >
Lisp/Scheme  |  1993-06-26  |  109KB  |  2,864 lines

  1. ;;; cplus-md1.el --- major mode for editing C++ (and C) code
  2.  
  3. ;; Author: 1992 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com>
  4. ;;         1987 Dave Detlefs and Stewart Clamen
  5. ;;         1985 Richard M. Stallman
  6. ;; Maintainer: c++-mode-help@anthem.nlm.nih.gov
  7. ;; Created: a long, long, time ago. adapted from the original c-mode.el
  8. ;; Version:         2.353
  9. ;; Last Modified:   1993/06/23 13:58:52
  10. ;; Keywords: C++ C editing major-mode
  11.  
  12. ;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  13.  
  14. ;; This file is part of GNU Emacs.
  15.  
  16. ;; GNU Emacs is free software; you can redistribute it and/or modify
  17. ;; it under the terms of the GNU General Public License as published by
  18. ;; the Free Software Foundation; either version 2, or (at your option)
  19. ;; any later version.
  20.  
  21. ;; GNU Emacs is distributed in the hope that it will be useful,
  22. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. ;; GNU General Public License for more details.
  25.  
  26. ;; You should have received a copy of the GNU General Public License
  27. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  28. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. ;; Introduction
  31. ;; ============
  32. ;; Do a "C-h m" in a c++-mode buffer for more information on
  33. ;; customizing c++-mode.  To submit bug reports hit "C-c C-b" in a
  34. ;; c++-mode buffer.  This runs the command c++-submit-bug-report and
  35. ;; automatically sets up the mail buffer with all the necessary
  36. ;; information.  If you have other questions contact me at the
  37. ;; following address: c++-mode-help@anthem.nlm.nih.gov.  Please don't
  38. ;; send bug reports to my personal account, I may not get it for a
  39. ;; long time.
  40.  
  41. ;; Notes for Novice Users
  42. ;; ======================
  43. ;; c++-mode facilitates editing of C++ code by automatically handling
  44. ;; the indentation of lines of code in a manner very similar to c-mode
  45. ;; as distributed with GNU Emacs.  Refer to the GNU Emacs manual,
  46. ;; chapter 21 for more information on "Editing Programs".  In fact,
  47. ;; c++-mode (through its companion mode entry point c++-c-mode) can
  48. ;; also be used to edit both K&R and ANSI C code!
  49. ;;
  50. ;; To use c++-mode, add the following to your .emacs file.  This
  51. ;; assumes you will use .cc or .C extensions for your C++ source:
  52. ;;
  53. ;; (autoload 'c++-mode   "c++-mode" "C++ Editing Mode" t)
  54. ;; (autoload 'c++-c-mode "c++-mode" "C Editing Mode" t)
  55. ;; (setq auto-mode-alist
  56. ;;   (append '(("\\.C$"  . c++-mode)
  57. ;;             ("\\.cc$" . c++-mode)
  58. ;;             ("\\.c$"  . c++-c-mode)   ; to edit C code
  59. ;;             ("\\.h$"  . c++-c-mode)   ; to edit C code
  60. ;;            ) auto-mode-alist))
  61. ;;
  62. ;; If you want to use the default c-mode for editing C code, then just
  63. ;; omit the lines marked "to edit C code".
  64. ;;
  65. ;; Finally, you may want to customize certain c++-mode variables.  The
  66. ;; best place to do this is in the mode hook variable called
  67. ;; c++-mode-hook.  Again, see the Emacs manual, chapter 21 for more
  68. ;; information.
  69.  
  70. ;; Important Note about Escapes in Comments, and Performance
  71. ;; =========================================================
  72. ;; You may notice that certain characters, when typed in comment
  73. ;; regions, get escaped with a backslash.  This is a workaround for
  74. ;; bugs in Emacs' syntax parsing algorithms.  In brief, syntax parsing
  75. ;; in Emacs 18 and derivatives is broken because syntax tables are not
  76. ;; rich enough to support more than 1 comment style per mode (as C++
  77. ;; requires).  The result is that Emacs will sometimes choke on
  78. ;; unbalanced parentheses and single quotes in comments.  Please do a
  79. ;; "C-h v c++-untame-characters" for more information.
  80. ;;
  81. ;; This problem affect both the accuracy and performance of c++-mode
  82. ;; because some parsing must be performed in Emacs lisp instead of
  83. ;; relying on the C primitives.  In general, I've chosen accuracy over
  84. ;; performance, but have worked hard to give moderately acceptable
  85. ;; speed in all but the most uncommon situations.  You will most likely
  86. ;; notice c++-mode slowing when you're editing a file of preprocessor
  87. ;; commands, or inside long functions or class definitions.
  88. ;; Optimization is an ongoing concern, but the real solution is to fix
  89. ;; Emacs.
  90. ;;
  91. ;; As of release 19.4, Lucid Emacs is distributed with the fixes in
  92. ;; place, and c++-mode will automatically take advantage of them so
  93. ;; none of the above applies to you.  Similar patches will be part of
  94. ;; FSF GNU Emacs 19.  Some patches for GNU Emacs 18 have been released
  95. ;; on the beta site, but they are unsupported.  Email for more
  96. ;; information.
  97.  
  98. ;; Beta Testers Mailing List
  99. ;; =========================
  100. ;; Want to be a c++-mode victim, er, beta-tester?  Send add/drop
  101. ;; requests to c++-mode-victims-request@anthem.nlm.nih.gov.
  102. ;; Discussions go to c++-mode-victims@anthem.nlm.nih.gov, but bug
  103. ;; reports and such should still be sent to c++-mode-help only.
  104. ;;
  105. ;; Many, many thanks go out to all the folks on the beta test list.
  106. ;; Without their patience, testing, insight, and code contribution,
  107. ;; c++-mode.el would be a far inferior package.
  108.  
  109. ;; Getting c++-mode.el
  110. ;; ===================
  111. ;; The latest public release version of this file should always be
  112. ;; available for anonymous ftp on the Emacs lisp archive machine.  The
  113. ;; path to the file is:
  114. ;;
  115. ;; archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/modes/c++-mode.el.Z 
  116. ;; 
  117. ;; For those of you without anon-ftp access, you can use the DEC's
  118. ;; ftpmail'er at the address ftpmail@decwrl.dec.com.  Send the
  119. ;; following message in the body of your mail to that address to get
  120. ;; c++-mode:
  121. ;;
  122. ;; reply <a valid net address back to you>
  123. ;; connect archive.cis.ohio-state.edu
  124. ;; binary
  125. ;; uuencode
  126. ;; chdir pub/gnu/emacs/elisp-archive/modes
  127. ;; get c++-mode.el.Z
  128. ;;
  129. ;; or just send the message "help" for more information on ftpmail.
  130. ;; Response times will vary with the number of requests in the queue.
  131.  
  132. ;; LCD Archive Entry:
  133. ;; c++-mode|Barry A. Warsaw|c++-mode-help@anthem.nlm.nih.gov
  134. ;; |Mode for editing C++, and ANSI/K&R C code (was Detlefs' c++-mode.el)
  135. ;; |1993/06/23 13:58:52|2.353|
  136.  
  137. ;;; Code:
  138.  
  139. ;; some people may not have c-mode loaded in by default.  c++-mode.el
  140. ;; unfortunately still depends on distrib c-mode.  c-mode doesn't
  141. ;; provide itself so this hack is best known way to ensure its loaded
  142. (or (fboundp 'c-mode)
  143.     (load "c-mode" nil t))
  144.  
  145.  
  146. ;; ======================================================================
  147. ;; user definable variables
  148. ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  149.  
  150. (defconst c++-emacs-features
  151.   (let ((mse-spec 'no-dual-comments)
  152.     (scanner 'v18))
  153.     ;; vanilla GNU18/Epoch 4 uses default values
  154.     (if (= 8 (length (parse-partial-sexp (point) (point))))
  155.     ;; we know we're using v19 style dual-comment specifications.
  156.     ;; All Lemacsen use 8-bit modify-syntax-entry flags, as do all
  157.     ;; patched FSF19, GNU18, Epoch4's.  Only vanilla FSF19 uses
  158.     ;; 1-bit flag.  Lets be as smart as we can about figuring this
  159.     ;; out.
  160.     (let ((table (copy-syntax-table)))
  161.       (modify-syntax-entry ?a ". 12345678" table)
  162.       (if (= (logand (lsh (aref table ?a) -16) 255) 255)
  163.           (setq mse-spec '8-bit)
  164.         (setq mse-spec '1-bit))
  165.       ;; we also know we're using a quicker, built-in comment
  166.       ;; scanner, but we don't know if its old-style or new.
  167.       ;; Fortunately we can ask emacs directly
  168.       (if (fboundp 'forward-comment)
  169.           (setq scanner 'v19)
  170.         (setq scanner 'old-v19))))
  171.     ;; now cobble up the necessary list
  172.     (list mse-spec scanner))
  173.   "A list of needed features extant in the Emacs you are using.
  174. There are many flavors of Emacs out on the net, each with different
  175. features supporting those needed by c++-mode.  Here's the current
  176. known list, along with the values for this variable:
  177.  
  178. Vanilla GNU 18/Epoch 4:  (no-dual-comments v18)
  179. GNU 18/Epoch 4 (patch1): (8-bit old-v19)
  180. GNU 18/Epoch 4 (patch2): (8-bit v19)
  181. Lemacs 19.4 - 19.7:      (8-bit old-v19)
  182. Lemacs 19.8 and over:    (8-bit v19)
  183. FSF 19:                  (1-bit v19)
  184. FSF 19 (patched):        (8-bit v19)")
  185.  
  186. (defvar c++-mode-abbrev-table nil
  187.   "Abbrev table in use in c++-mode buffers.")
  188. (define-abbrev-table 'c++-mode-abbrev-table ())
  189.  
  190. (defvar c++-mode-map ()
  191.   "Keymap used in c++-mode.")
  192. (if c++-mode-map
  193.     ()
  194.   (setq c++-mode-map (make-sparse-keymap))
  195.   (define-key c++-mode-map "\C-j"      'reindent-then-newline-and-indent)
  196.   (define-key c++-mode-map "{"         'c++-electric-brace)
  197.   (define-key c++-mode-map "}"         'c++-electric-brace)
  198.   (define-key c++-mode-map ";"         'c++-electric-semi)
  199.   (define-key c++-mode-map "#"         'c++-electric-pound)
  200.   (define-key c++-mode-map "\e\C-h"    'mark-c-function)
  201.   (define-key c++-mode-map "\e\C-q"    'c++-indent-exp)
  202.   (define-key c++-mode-map "\t"        'c++-indent-command)
  203.   (define-key c++-mode-map "\C-c\C-i"  'c++-insert-header)
  204.   (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region)
  205.   (define-key c++-mode-map "\C-c\C-c"  'c++-comment-region)
  206.   (define-key c++-mode-map "\C-c\C-u"  'c++-uncomment-region)
  207.   (define-key c++-mode-map "\C-c\C-x"  'c++-match-paren)
  208.   (define-key c++-mode-map "\e\C-a"    'c++-beginning-of-defun)
  209.   (define-key c++-mode-map "\e\C-e"    'c++-end-of-defun)
  210.   (define-key c++-mode-map "\e\C-x"    'c++-indent-defun)
  211.   (define-key c++-mode-map "/"         'c++-electric-slash)
  212.   (define-key c++-mode-map "*"         'c++-electric-star)
  213.   (define-key c++-mode-map ":"         'c++-electric-colon)
  214.   (define-key c++-mode-map "\177"      'c++-electric-delete)
  215.   (define-key c++-mode-map "\C-c\C-t"  'c++-toggle-auto-hungry-state)
  216.   (define-key c++-mode-map "\C-c\C-h"  'c++-toggle-hungry-state)
  217.   (define-key c++-mode-map "\C-c\C-a"  'c++-toggle-auto-state)
  218.   (if (memq 'v18 c++-emacs-features)
  219.       (progn
  220.     (define-key c++-mode-map "\C-c'"     'c++-tame-comments)
  221.     (define-key c++-mode-map "'"         'c++-tame-insert)
  222.     (define-key c++-mode-map "["         'c++-tame-insert)
  223.     (define-key c++-mode-map "]"         'c++-tame-insert)
  224.     (define-key c++-mode-map "("         'c++-tame-insert)
  225.     (define-key c++-mode-map ")"         'c++-tame-insert)))
  226.   (define-key c++-mode-map "\C-c\C-b"  'c++-submit-bug-report)
  227.   (define-key c++-mode-map "\C-c\C-v"  'c++-version)
  228.   ;; these are necessary because default forward-sexp and
  229.   ;; backward-sexp don't automatically let-bind
  230.   ;; parse-sexp-ignore-comments, which is needed for them to work
  231.   ;; properly in a C++ buffer.
  232.   (define-key c++-mode-map "\e\C-f"    'c++-forward-sexp)
  233.   (define-key c++-mode-map "\e\C-b"    'c++-backward-sexp)
  234.   )
  235.  
  236. (defvar c++-mode-syntax-table nil
  237.   "Syntax table used in c++-mode buffers.")
  238. (defvar c++-c-mode-syntax-table nil
  239.   "Syntax table used in c++-c-mode buffers.")
  240.  
  241. (if c++-mode-syntax-table
  242.     ()
  243.   (setq c++-mode-syntax-table (make-syntax-table))
  244.   (modify-syntax-entry ?\\ "\\"    c++-mode-syntax-table)
  245.   (modify-syntax-entry ?+  "."     c++-mode-syntax-table)
  246.   (modify-syntax-entry ?-  "."     c++-mode-syntax-table)
  247.   (modify-syntax-entry ?=  "."     c++-mode-syntax-table)
  248.   (modify-syntax-entry ?%  "."     c++-mode-syntax-table)
  249.   (modify-syntax-entry ?<  "."     c++-mode-syntax-table)
  250.   (modify-syntax-entry ?>  "."     c++-mode-syntax-table)
  251.   (modify-syntax-entry ?&  "."     c++-mode-syntax-table)
  252.   (modify-syntax-entry ?|  "."     c++-mode-syntax-table)
  253.   (modify-syntax-entry ?\' "\""    c++-mode-syntax-table)
  254.   ;; comment syntax
  255.   (cond
  256.    ((memq '8-bit c++-emacs-features)
  257.     ;; Lucid emacs has the best implementation
  258.     (modify-syntax-entry ?/  ". 1456" c++-mode-syntax-table)
  259.     (modify-syntax-entry ?*  ". 23"   c++-mode-syntax-table)
  260.     (modify-syntax-entry ?\n "> b"    c++-mode-syntax-table))
  261.    ((memq '1-bit c++-emacs-features)
  262.     ;; FSF19 has sub-optimal, but workable implementation
  263.     ;; Some strange behavior may be encountered.  LOBBY FSF!
  264.     (modify-syntax-entry ?/  ". 124" c++-mode-syntax-table)
  265.     (modify-syntax-entry ?*  ". 23b" c++-mode-syntax-table)
  266.     (modify-syntax-entry ?\n ">"     c++-mode-syntax-table))
  267.    (t
  268.     ;; Vanilla GNU18 is just plain busted.  We'll do the best we can,
  269.     ;; but some strange behavior may be encountered.  PATCH or UPGRADE!
  270.     (modify-syntax-entry ?/  ". 124" c++-mode-syntax-table)
  271.     (modify-syntax-entry ?*  ". 23"  c++-mode-syntax-table)
  272.     (modify-syntax-entry ?\n ">"     c++-mode-syntax-table))
  273.    ))
  274.  
  275. (if c++-c-mode-syntax-table
  276.     ()
  277.   (setq c++-c-mode-syntax-table (make-syntax-table))
  278.   (modify-syntax-entry ?\\ "\\"    c++-c-mode-syntax-table)
  279.   (modify-syntax-entry ?+  "."     c++-c-mode-syntax-table)
  280.   (modify-syntax-entry ?-  "."     c++-c-mode-syntax-table)
  281.   (modify-syntax-entry ?=  "."     c++-c-mode-syntax-table)
  282.   (modify-syntax-entry ?%  "."     c++-c-mode-syntax-table)
  283.   (modify-syntax-entry ?<  "."     c++-c-mode-syntax-table)
  284.   (modify-syntax-entry ?>  "."     c++-c-mode-syntax-table)
  285.   (modify-syntax-entry ?&  "."     c++-c-mode-syntax-table)
  286.   (modify-syntax-entry ?|  "."     c++-c-mode-syntax-table)
  287.   (modify-syntax-entry ?\' "\""    c++-c-mode-syntax-table)
  288.   (modify-syntax-entry ?/  ". 14"  c++-c-mode-syntax-table)
  289.   (modify-syntax-entry ?*  ". 23"  c++-c-mode-syntax-table)
  290.   )
  291.  
  292. (defvar c++-tab-always-indent
  293.   (if (boundp 'c-tab-always-indent) c-tab-always-indent t)
  294.   "*Controls the operation of the TAB key.
  295. If t (the default), always just indent the current line.  If nil,
  296. indent the current line only if point is at the left margin or in the
  297. line's indentation; otherwise insert a tab.  If not-nil-or-t, then tab
  298. is inserted only within literals (comments and strings) and inside
  299. preprocessor directives, but line is always reindented.")
  300. (defvar c++-always-arglist-indent-p nil
  301.   "*Control indentation of continued arglists.
  302. When non-nil, arglists continued on subsequent lines will always
  303. indent `c++-empty-arglist-indent' spaces, otherwise, they will indent to
  304. just under previous line's argument indentation.")
  305. (defvar c++-block-close-brace-offset 0
  306.   "*Extra indentation given to close braces which close a block.
  307. This variable can be either an integer or a list.  If an integer, it
  308. describes the extra offset given a block closing brace (and a closing
  309. paren if `c++-paren-as-block-close-p' is non-nil), treating all
  310. closing parens the same.  If a list of the form (OTHERS . TOPLEVEL),
  311. OTHERS is an integer describing the offset given to all but top-level
  312. (e.g. function) closing braces, while TOPLEVEL is an integer
  313. describing offset given only to braces which close top-level
  314. constructs.")
  315. (defvar c++-paren-as-block-close-p nil
  316.   "*Treat a parenthesis which is the first non-whitespace on a line as
  317. a paren which closes a block.  When non-nil, `c-indent-level' is
  318. subtracted, and `c++-block-close-brace-offset' is added to the line's
  319. offset.")
  320. (defvar c++-continued-member-init-offset nil
  321.   "*Extra indent for continuation lines of member inits; nil means to align
  322. with previous initializations rather than with the colon on the first line.")
  323. (defvar c++-member-init-indent 0
  324.   "*Indentation level of member initializations in function declarations.")
  325. (defvar c++-friend-offset -4
  326.   "*Offset of C++ friend class declarations relative to member declarations.")
  327. (defvar c++-access-specifier-offset c-label-offset
  328.   "*Extra indentation given to public, protected, and private labels.")
  329. (defvar c++-empty-arglist-indent nil
  330.   "*Indicates how far to indent a line following an empty argument list.
  331. Nil means indent to just after the paren.")
  332. (defvar c++-comment-only-line-offset 0
  333.   "*Indentation offset for line which contains only C or C++ style comments.
  334. This variable can take either a single integer or a list of integers.
  335. If a single integer this is the extra indentation offset to apply to
  336. all comment-only lines, except those which start in column zero.  If a
  337. list is used, the first integer is for all non-column-zero
  338. comment-only lines and the second integer is for all column-zero
  339. lines.  You can also use a list containing only 1 integer, in which
  340. case, this value is used for all comment-only lines.  For example:
  341.  
  342. value     meaning
  343. =====     =======
  344.   0       comment-only lines do not indent
  345.   4       non-col0 lines indent 4 spaces, col0 lines don't indent
  346. '(4)      all comment-only lines indent 4 spaces
  347. '(4 1)    non-col0 lines indent 4 spaces, col0 lines indent 1 space")
  348.  
  349. (defvar c++-C-block-comments-indent-p nil
  350.   "*4 styles of C block comments are supported.  If this variable is nil,
  351. then styles 1-3 are supported.  If this variable is non-nil, style 4 is
  352. supported.
  353. style 1:       style 2:       style 3:       style 4:
  354. /*             /*             /*             /*
  355.    blah         * blah        ** blah        blah
  356.    blah         * blah        ** blah        blah
  357.    */           */            */             */
  358. ")
  359. (defvar c++-cleanup-list nil
  360.   "*List of various C++ constructs to \"clean up\".
  361. These cleanups only take place when the auto-newline feature is turned
  362. on, as evidenced by the `/a' or `/ah' appearing next to the mode name.
  363.  
  364. Current legal values are:
  365.  `brace-else-brace'   -- clean up `} else {' constructs by placing entire
  366.                          construct on a single line.  This cleanup only
  367.                          takes place when there is nothing but white
  368.                          space between the braces and the else.  
  369.  `empty-defun-braces' -- cleans up empty C++ function braces by
  370.                          placing them on the same line.
  371.  `defun-close-semi'   -- cleans up the terminating semi-colon on class
  372.                          definitions and functions by placing the semi
  373.                          on the same line as the closing brace.")
  374. (defvar c++-hanging-braces t
  375.   "*Controls the insertion of newlines before open (left) braces.
  376. This variable only has effect when auto-newline is on, as evidenced by
  377. the `/a' or `/ah' appearing next to the mode name.  If nil, open
  378. braces do not hang (i.e. a newline is inserted before all open
  379. braces).  If t, all open braces hang -- no newline is inserted before
  380. open braces.  If not nil or t, newlines are only inserted before
  381. top-level open braces; all other braces hang.")
  382. (defvar c++-hanging-member-init-colon 'before
  383.   "*Defines how colons which introduce member initializations are formatted.
  384. Legal values are:
  385.   t        -- no newlines inserted before or after colon
  386.   nil      -- newlines inserted before and after colon
  387.   `after'  -- newlines inserted only after colon
  388.   `before` -- newlines inserted only before colon")
  389. (defvar c++-auto-hungry-initial-state 'none
  390.   "*Initial state of auto/hungry features when buffer is first visited.
  391. Legal values are:
  392.   `none'         -- no auto-newline and no hungry-delete-key.
  393.   `auto-only'    -- auto-newline, but no hungry-delete-key.
  394.   `hungry-only'  -- no auto-newline, but hungry-delete-key.
  395.   `auto-hungry'  -- both auto-newline and hungry-delete-key enabled.
  396. Nil is synonymous for `none' and t is synonymous for `auto-hungry'.")
  397.  
  398. (defvar c++-auto-hungry-toggle t
  399.   "*Enable/disable toggling of auto/hungry features.
  400. Legal values are:
  401.   `none'         -- auto-newline and hungry-delete-key cannot be enabled.
  402.   `auto-only'    -- only auto-newline feature can be toggled.
  403.   `hungry-only'  -- only hungry-delete-key feature can be toggled.
  404.   `auto-hungry'  -- both auto-newline and hungry-delete-key can be toggled.
  405. Nil is synonymous for `none' and t is synonymous for `auto-hungry'.")
  406.  
  407. (defvar c++-relative-offset-p t
  408.   "*Control the calculation for indentation.
  409. When non-nil (the default), indentation is calculated relative to the
  410. first statement in the block.  When nil, the indentation is calculated
  411. without regard to how the first statement is indented.")
  412.  
  413. (defvar c++-untame-characters (and (memq 'v18 c++-emacs-features) '(?\'))
  414.   "*Utilize a backslashing workaround of an Emacs syntax parsing bug.
  415. If non-nil, this variable should contain a list of characters which
  416. will be prepended by a backslash in comment regions.  By default, the
  417. list contains only the most troublesome character, the single quote.
  418. To be completely safe, set this variable to:
  419.  
  420.     '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\])
  421.  
  422. This is the full list of characters which can potentially cause
  423. problems if they exist unbalanced within comments.  Setting this
  424. variable to nil will defeat this feature, but be forewarned!  Such
  425. un-escaped characters in comment regions can potentially break many
  426. things such as some indenting and blinking of parenthesis.
  427.  
  428. Note further that only the default set of characters will be escaped
  429. automatically as they are typed.  But, executing `c++-tame-comments'
  430. (\\[c++-tame-comments]) will escape all characters which are members
  431. of this set, and which are found in comments throughout the file.
  432.  
  433. Finally, c++-mode can tell if you're running a patched Emacs.  If so,
  434. taming characters isn't necessary and this variable is automatically
  435. set to nil.")
  436.  
  437. (defvar c++-default-macroize-column 78
  438.   "*Column to insert backslashes.")
  439. (defvar c++-special-indent-hook nil
  440.   "*Hook for user defined special indentation adjustments.
  441. This hook gets called after a line is indented by the mode.  By
  442. supplying a hook, you can make adjustments to the line's standard
  443. indentation.  If you do use this hook, you will likely need to also
  444. set `c++-relative-offset-p' to nil.  The call to this hook is wrapped in
  445. a `save-excursion' so you don't need to worry about restoring point and
  446. mark inside the hook function.")
  447. (defvar c++-delete-function 'backward-delete-char-untabify
  448.   "*Function called by `c++-electric-delete' when deleting a single char.")
  449. (defvar c++-electric-pound-behavior nil
  450.   "*List of behaviors for electric pound insertion.
  451. Only currently supported behavior is `alignleft'.")
  452. (defvar c++-backscan-limit 2000
  453.   "*Limit in characters for looking back while skipping syntactic ws.
  454. If you typically write really big methods, and start noticing
  455. incorrect indentations, try cranking this value up.  The larger this
  456. value is, though, the slower parts of c++-mode can become.  Setting
  457. this variable to nil defeats backscan limits.")
  458.  
  459. ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  460. ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
  461. ;; 
  462. (defvar c++-hungry-delete-key nil
  463.   "Internal state of hungry delete key feature.")
  464. (defvar c++-auto-newline nil
  465.   "Internal state of auto newline feature.")
  466.  
  467. (make-variable-buffer-local 'c++-auto-newline)
  468. (make-variable-buffer-local 'c++-hungry-delete-key)
  469.  
  470. (defconst c++-access-key "\\<\\(public\\|protected\\|private\\)\\>:"
  471.   "Regexp which describes access specification keywords.")
  472. (defconst c++-class-key
  473.   (concat
  474.    "\\(\\(extern\\|typedef\\)\\s +\\)?"
  475.    "\\(template\\s *<[^>]*>\\s *\\)?"
  476.    "\\<\\(class\\|struct\\|union\\)\\>")
  477.   "Regexp which describes a class declaration, including templates.")
  478. (defconst c++-inher-key
  479.   (concat "\\(\\<static\\>\\s +\\)?"
  480.       c++-class-key
  481.       "[ \t]+\\(\\(\\w\\|_\\)+[ \t]*:[ \t]*\\)?")
  482.   "Regexp which describes a class inheritance declaration.")
  483.  
  484.  
  485. ;; ======================================================================
  486. ;; c++-mode main entry point
  487. ;; ======================================================================
  488. (defun c++-mode ()
  489.   "Major mode for editing C++ code.  2.353
  490. To submit a problem report, enter `\\[c++-submit-bug-report]' from a
  491. c++-mode buffer.  This automatically sets up a mail buffer with
  492. version information already added.  You just need to add a description
  493. of the problem and send the message.
  494.  
  495. 1. Very much like editing C code,
  496. 2. Expression and list commands understand all C++ brackets,
  497. 3. Tab at left margin indents for C++ code,
  498. 4. Both C++ and C style block comments are recognized,
  499. 5. Paragraphs are separated by blank lines only,
  500. 6. Hungry delete key and auto newline features are optional.
  501.  
  502. IMPORTANT NOTE: You may notice that some characters (by default, only
  503. single quote) will get escaped with a backslash when typed in a
  504. comment region.  This is a necessary workaround of a bug present in
  505. GNU Emacs 18 and derivatives.  Enter `\\[describe-variable] c++-untame-characters RET'
  506. for more information.  If you are running a patched Emacs, no
  507. characters will be escaped in comment regions, and many functions will
  508. run much faster.
  509.  
  510. Key bindings:
  511. \\{c++-mode-map}
  512.  
  513. These variables control indentation style.  Those with names like
  514. c-<thing> are inherited from c-mode.  Those with names like
  515. c++-<thing> are unique for this mode, or have extended functionality
  516. from their c-mode cousins.
  517.  
  518.  c-argdecl-indent
  519.     Indentation level of declarations of C function arguments.
  520.  c-brace-imaginary-offset
  521.     An open brace following other text is treated as if it were
  522.     this far to the right of the start of its line.
  523.  c-brace-offset
  524.     Extra indentation for line if it starts with an open brace.
  525.  c-continued-brace-offset
  526.     Extra indentation given to a brace that starts a substatement.
  527.     This is in addition to `c-continued-statement-offset'.
  528.  c-continued-statement-offset
  529.     Extra indentation given to a substatement, such as the
  530.     then-clause of an if or body of a while.
  531.  c-indent-level
  532.     Indentation of C statements within surrounding block.
  533.     The surrounding block's indentation is the indentation
  534.     of the line on which the open-brace appears.
  535.  c-label-offset
  536.     Extra indentation for line that is a label, or case or `default:'.
  537.  
  538.  c++-C-block-comments-indent-p
  539.     Style of C block comments to support.
  540.  c++-access-specifier-offset
  541.     Extra indentation given to public, protected, and private keyword lines.
  542.  c++-always-arglist-indent-p
  543.     Control indentation of continued arglists.  When non-nil, arglists
  544.     continued on subsequent lines will always indent
  545.     `c++-empty-arglist-indent' spaces, otherwise, they will indent to
  546.     just under previous line's argument indentation.
  547.  c++-auto-hungry-initial-state
  548.     Initial state of auto/hungry feature when a C++ buffer is first visited.
  549.  c++-auto-hungry-toggle
  550.     Enable/disable toggling of auto/hungry features.
  551.  c++-backscan-limit
  552.     Limit in characters for looking back while skipping syntactic
  553.     whitespace.  This variable is only used in an un-patched Emacs to
  554.     help improve performance at the expense of some accuracy.  Patched
  555.     Emacses are both fast and accurate.
  556.  c++-block-close-brace-offset
  557.     Extra indentation give to braces which close a block.
  558.  c++-cleanup-list
  559.     A list of construct \"clean ups\" which c++-mode will perform when
  560.     auto-newline feature is on.  Current legal values are:
  561.     `brace-else-brace', `empty-defun-braces', `defun-close-semi'.
  562.  c++-comment-only-line-offset
  563.     Extra indentation for a line containing only a C or C++ style
  564.     comment.  Can be an integer or list, specifying the various styles
  565.     of comment-only line special indentations.
  566.  c++-continued-member-init-offset
  567.     Extra indentation for continuation lines of member initializations; nil
  568.     means to align with previous initializations rather than with the colon.
  569.  c++-default-macroize-column
  570.     Column to insert backslashes when macroizing a region.
  571.  c++-delete-function
  572.     Function called by `c++-electric-delete' when deleting a single char.
  573.  c++-electric-pound-behavior
  574.     List of behaviors for electric pound insertion.
  575.  c++-empty-arglist-indent
  576.     Extra indentation to apply to a line following an empty argument
  577.     list.  nil means to line it up with the left paren.
  578.  c++-friend-offset
  579.     Offset of C++ friend class declarations relative to member declarations.
  580.  c++-hanging-braces
  581.     Controls open brace hanging behavior when using auto-newline feature.
  582.     nil says no braces hang, t says all open braces hang.  non-nil-or-t
  583.     means top-level open braces don't hang, all others do.
  584.  c++-hanging-member-init-colon
  585.     Defines how colons which introduce member initialization lists are
  586.     formatted.  t means no newlines are inserted either before or after
  587.     the colon.  nil means newlines are inserted both before and after
  588.     the colon.  `before' inserts newlines only before the colon, and
  589.     `after' inserts newlines only after colon.
  590.  c++-member-init-indent
  591.     Indentation level of member initializations in function declarations,
  592.     if they are on a separate line beginning with a colon.
  593.  c++-paren-as-block-close-p
  594.     If non-nil, treat a parenthesis which is the first non-whitespace
  595.     on a line as a paren which closes a block (i.e. treat it similar
  596.     to right curly brace).
  597.  c++-relative-offset-p
  598.     Control the calculation for indentation.  When non-nil (the
  599.     default), indentation is calculated relative to the first
  600.     statement in the block.  When nil, the indentation is calculated
  601.     without regard to how the first statement is indented.  Useful when
  602.     using a `c++-special-indent-hook'.
  603.  c++-special-indent-hook
  604.     Hook for user defined special indentation adjustments.  You can use
  605.     this hook, which gets called after a line is indented by the mode,
  606.     to customize indentations of the line.
  607.  c++-tab-always-indent
  608.     Controls the operation of the TAB key.  t means always just indent
  609.     the current line.  nil means indent the current line only if point
  610.     is at the left margin or in the line's indentation; otherwise
  611.     insert a tab.  Any other value means insert tab only within
  612.     literals (comments and strings) and inside preprocessor
  613.     directives, but always reindent the line.  The default is value
  614.     for `c-tab-always-indent'.
  615.  c++-untame-characters
  616.     When non-nil, inserts backslash escapes before certain untamed
  617.     characters in comment regions.  It is recommended that you keep the
  618.     default setting to workaround a nasty Emacs bug, unless you are
  619.     running a patched Emacs.
  620.  
  621. Auto-newlining is no longer an all or nothing proposition.  In my
  622. opinion, I don't believe it is possible to implement a perfect
  623. auto-newline algorithm.  Sometimes you want it and sometimes you don't.
  624. So now auto-newline (and its companion feature, hungry-delete-key) can
  625. be toggled on and off on the fly.  Hungry-delete-key is the optional
  626. behavior of the delete key so that, when enabled, hitting the delete
  627. key once consumes all preceding whitespace, unless point is within a
  628. literal (defined as a C or C++ comment, or string).  Inside literals,
  629. and with hungry-delete-key disabled, the delete key just calls the
  630. function in variable `c++-delete-function'.
  631.  
  632. Selection and toggling of these features is controlled by the
  633. variables `c++-auto-hungry-initial-state' and `c++-auto-hungry-toggle'.
  634. Legal values for both variables are:
  635.  
  636.   `none' (or nil)      -- no auto-newline or hungry-delete-key.
  637.   `auto-only'          -- function affects only auto-newline feature.
  638.   `hungry-only'        -- function affects only hungry-delete-key feature.
  639.   `auto-hungry' (or t) -- function affects both features.
  640.  
  641. Thus if `c++-auto-hungry-initial-state' is `hungry-only', then only
  642. hungry-delete-key feature is turned on when the buffer is first
  643. visited.  If `c++-auto-hungry-toggle' is `auto-hungry', and both
  644. auto-newline and hungry-delete-key features are on, then hitting
  645. `\\[c++-toggle-auto-hungry-state]' will toggle both features.  Hitting
  646. `\\[c++-toggle-hungry-state]' will always toggle hungry-delete-key
  647. feature and hitting `\\[c++-toggle-auto-state]' will always toggle
  648. auto-newline feature, regardless of the value of
  649. `c++-auto-hungry-toggle'.
  650.  
  651. Settings for K&R, BSD, and Stroustrup indentation styles are
  652.   c-indent-level                5    8    4
  653.   c-continued-statement-offset  5    8    4
  654.   c-continued-brace-offset                0
  655.   c-brace-offset               -5   -8    0
  656.   c-brace-imaginary-offset                0
  657.   c-argdecl-indent              0    8    4
  658.   c-label-offset               -5   -8   -4
  659.   c++-access-specifier-offset  -5   -8   -4
  660.   c++-empty-arglist-indent                4
  661.   c++-friend-offset                       0
  662.  
  663. Turning on C++ mode calls the value of the variable `c++-mode-hook' with
  664. no args, if that value is non-nil."
  665.   (interactive)
  666.   (kill-all-local-variables)
  667.   (use-local-map c++-mode-map)
  668.   (set-syntax-table c++-mode-syntax-table)
  669.   (setq major-mode 'c++-mode
  670.     mode-name "C++"
  671.     local-abbrev-table c++-mode-abbrev-table)
  672.   (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter))
  673.   (set (make-local-variable 'paragraph-separate) paragraph-start)
  674.   (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
  675.   (set (make-local-variable 'require-final-newline) t)
  676.   (set (make-local-variable 'parse-sexp-ignore-comments) nil)
  677.   ;; 
  678.   (set (make-local-variable 'indent-line-function) 'c++-indent-line)
  679.   (set (make-local-variable 'comment-start) "// ")
  680.   (set (make-local-variable 'comment-end) "")
  681.   (set (make-local-variable 'comment-column) 32)
  682.   (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *")
  683.   (set (make-local-variable 'comment-indent-hook) 'c++-comment-indent)
  684.   ;; hack auto-hungry designators into mode-line-format
  685.   (if (listp mode-line-format)
  686.       (setq mode-line-format
  687.         (let ((modeline nil))
  688.           (mapcar
  689.            (function
  690.         (lambda (element)
  691.           (setq modeline
  692.             (append modeline
  693.                 (if (eq element 'mode-name)
  694.                     '(mode-name (c++-hungry-delete-key
  695.                          (c++-auto-newline "/ah" "/h")
  696.                          (c++-auto-newline "/a")))
  697.                   (list element))))))
  698.            mode-line-format)
  699.           modeline)))
  700.   (run-hooks 'c++-mode-hook)
  701.   (c++-set-auto-hungry-state
  702.    (memq c++-auto-hungry-initial-state '(auto-only   auto-hungry t))
  703.    (memq c++-auto-hungry-initial-state '(hungry-only auto-hungry t))))
  704.  
  705. (defun c++-c-mode ()
  706.   "Major mode for editing K&R and ANSI C code.  2.353
  707. This mode is based on c++-mode.  Documentation for this mode is
  708. available by doing a `\\[describe-function] c++-mode'."
  709.   (interactive)
  710.   (c++-mode)
  711.   (setq major-mode 'c++-c-mode
  712.     mode-name "C"
  713.     local-abbrev-table c-mode-abbrev-table)
  714.   (setq comment-start "/* "
  715.     comment-end   " */")
  716.   ;; some syntax differences are necessary for C vs. C++
  717.   (set-syntax-table c++-c-mode-syntax-table)
  718.   (run-hooks 'c++-c-mode-hook))
  719.  
  720. (defun c++-comment-indent ()
  721.   "Used by `indent-for-comment' to decide how much to indent a comment
  722. in C++ code based on its context."
  723.   (if (looking-at "^\\(/\\*\\|//\\)")
  724.       0                    ; Existing comment at bol stays there.
  725.     (save-excursion
  726.       (skip-chars-backward " \t")
  727.       (max
  728.        ;; leave at least one space on non-empty lines.
  729.        (if (zerop (current-column))
  730.        0
  731.      (1+ (current-column)))
  732.        ;; use comment-column if previous line is comment only line
  733.        ;; indented to the left of comment-column
  734.        (save-excursion
  735.      (beginning-of-line)
  736.      (if (not (bobp)) (forward-line -1))
  737.      (skip-chars-forward " \t")
  738.      (if (looking-at "/\\*\\|//")
  739.          (if (< (current-column) comment-column)
  740.          comment-column
  741.            (current-column))
  742.        0))
  743.        (let ((cur-pt (point)))
  744.      (beginning-of-line 0)
  745.      ;; If previous line had a comment, use it's indent
  746.      (if (re-search-forward comment-start-skip cur-pt t)
  747.          (progn
  748.            (goto-char (match-beginning 0))
  749.            (current-column))
  750.        comment-column))))))        ; otherwise indent at comment column.
  751.  
  752.  
  753. ;; ======================================================================
  754. ;; most command level (interactive) and related
  755. ;; ======================================================================
  756. (defun c++-set-auto-hungry-state (auto-p hungry-p)
  757.   "Set auto/hungry to state indicated by AUTO-P and HUNGRY-P.
  758. Update mode line to indicate state to user."
  759.   (setq c++-auto-newline auto-p
  760.     c++-hungry-delete-key hungry-p)
  761.   (set-buffer-modified-p (buffer-modified-p)))
  762.  
  763. (defun c++-toggle-auto-state (arg)
  764.   "Toggle auto-newline feature.
  765. This function ignores `c++-auto-hungry-toggle' variable.  Optional
  766. numeric ARG, if supplied turns on auto-newline when positive, turns
  767. off auto-newline when negative and toggles when zero."
  768.   (interactive "P")
  769.   (let ((auto (cond
  770.            ((not arg)
  771.         (not c++-auto-newline))
  772.            ((zerop (setq arg (prefix-numeric-value arg)))
  773.         (not c++-auto-newline))
  774.            ((< arg 0) nil)
  775.            (t t))))
  776.     (c++-set-auto-hungry-state auto c++-hungry-delete-key)))
  777.  
  778. (defun c++-toggle-hungry-state (arg)
  779.   "Toggle hungry-delete-key feature.
  780. This function ignores `c++-auto-hungry-toggle' variable.  Optional
  781. numeric ARG, if supplied turns on hungry-delete-key when positive,
  782. turns off hungry-delete-key when negative and toggles when zero."
  783.   (interactive "P")
  784.   (let ((hungry (cond
  785.          ((not arg)
  786.           (not c++-hungry-delete-key))
  787.          ((zerop (setq arg (prefix-numeric-value arg)))
  788.           (not c++-hungry-delete-key))
  789.          ((< arg 0) nil)
  790.          (t t))))
  791.     (c++-set-auto-hungry-state c++-auto-newline hungry)))
  792.  
  793. (defun c++-toggle-auto-hungry-state (arg)
  794.   "Toggle auto-newline and hungry-delete-key features.
  795. Actual toggling of these features is controlled by
  796. `c++-auto-hungry-toggle' variable.
  797.  
  798. Optional argument has the following meanings when supplied:
  799.   Universal argument \\[universal-argument]
  800.         resets features to c++-auto-hungry-initial-state.
  801.   negative number
  802.         turn off both auto-newline and hungry-delete-key features.
  803.   positive number
  804.         turn on both auto-newline and hungry-delete-key features.
  805.   zero
  806.         toggle both features regardless of `c++-auto-hungry-toggle-p'."
  807.   (interactive "P")
  808.   (let* ((numarg (prefix-numeric-value arg))
  809.      (apl (list 'auto-only   'auto-hungry t))
  810.      (hpl (list 'hungry-only 'auto-hungry t))
  811.      (auto (cond
  812.         ((not arg)
  813.          (if (memq c++-auto-hungry-toggle apl)
  814.              (not c++-auto-newline)
  815.            c++-auto-newline))
  816.         ((listp arg)
  817.          (memq c++-auto-hungry-initial-state apl))
  818.         ((zerop numarg)
  819.          (not c++-auto-newline))
  820.         ((< arg 0) nil)
  821.         (t t)))
  822.      (hungry (cond
  823.           ((not arg)
  824.            (if (memq c++-auto-hungry-toggle hpl)
  825.                (not c++-hungry-delete-key)
  826.              c++-hungry-delete-key))
  827.           ((listp arg)
  828.            (memq c++-auto-hungry-initial-state hpl))
  829.           ((zerop numarg)
  830.            (not c++-hungry-delete-key))
  831.           ((< arg 0) nil)
  832.           (t t))))
  833.     (c++-set-auto-hungry-state auto hungry)))
  834.  
  835. (defun c++-tame-insert (arg)
  836.   "Safely inserts certain troublesome characters in comment regions.
  837. Because of syntax bugs in Emacs, characters with string or parenthesis
  838. syntax must be escaped with a backslash or lots of things get messed
  839. up.  Unfortunately, setting `parse-sexp-ignore-comments' to non-nil does
  840. not fix the problem, but this function is unnecessary if you are
  841. running a patched Emacs.
  842.  
  843. See also the variable `c++-untame-characters'."
  844.   (interactive "p")
  845.   (if (and (memq last-command-char c++-untame-characters)
  846.        (memq (c++-in-literal) '(c c++)))
  847.       (insert "\\"))
  848.   (self-insert-command arg))
  849.  
  850. (defun c++-electric-delete (arg)
  851.   "If `c++-hungry-delete-key' is non-nil, consumes all preceding
  852. whitespace unless ARG is supplied, or point is inside a C or C++ style
  853. comment or string.  If ARG is supplied, this just calls
  854. `backward-delete-char-untabify' passing along ARG.
  855.  
  856. If `c++-hungry-delete-key' is nil, just call `backward-delete-char-untabify'."
  857.   (interactive "P")
  858.   (cond
  859.    ((or (not c++-hungry-delete-key) arg)
  860.     (funcall c++-delete-function (prefix-numeric-value arg)))
  861.    ((let ((bod (c++-point 'bod)))
  862.       (not (or (memq (c++-in-literal bod) '(c c++ string))
  863.            (save-excursion
  864.          (skip-chars-backward " \t")
  865.          (= (preceding-char) ?#)))))
  866.     (let ((here (point)))
  867.       (skip-chars-backward " \t\n")
  868.       (if (/= (point) here)
  869.       (delete-region (point) here)
  870.     (funcall c++-delete-function 1))))
  871.    (t (funcall c++-delete-function 1))))
  872.  
  873. (defun c++-electric-pound (arg)
  874.   "Electric pound command."
  875.   (interactive "p")
  876.   (if (memq (c++-in-literal) '(c c++ string))
  877.       (self-insert-command arg)
  878.     (let ((here (point-marker))
  879.       (bobp (bobp))
  880.       (bolp (bolp)))
  881.       (if (memq 'alignleft c++-electric-pound-behavior)
  882.       (progn (beginning-of-line)
  883.          (delete-horizontal-space)))
  884.       (if bobp
  885.       (insert (make-string arg last-command-char))
  886.     (insert-before-markers (make-string arg last-command-char)))
  887.       (if (not bolp)
  888.       (goto-char here))
  889.       (set-marker here nil))))
  890.  
  891. (defun c++-electric-brace (arg)
  892.   "Insert character and correct line's indentation."
  893.   (interactive "P")
  894.   (let (insertpos
  895.     (last-command-char last-command-char)
  896.     (bod (c++-point 'bod)))
  897.     (if (and (not arg)
  898.          (save-excursion
  899.            (skip-chars-forward " \t")
  900.            (eolp))
  901.          (or (save-excursion
  902.            (skip-chars-backward " \t")
  903.            (bolp))
  904.          (let ((c++-auto-newline c++-auto-newline)
  905.                (open-brace-p (= last-command-char ?{)))
  906.            (if (and open-brace-p
  907.                 (or (eq c++-hanging-braces t)
  908.                 (and c++-hanging-braces
  909.                      (not (c++-at-top-level-p t bod)))))
  910.                (setq c++-auto-newline nil))
  911.            (if (c++-auto-newline)
  912.                ;; this may have auto-filled so we need to
  913.                ;; indent the previous line. we also need to
  914.                ;; indent the currently line, or
  915.                ;; c++-beginning-of-defun will not be able to
  916.                ;; correctly find the bod when
  917.                ;; c++-match-headers-strongly is nil.
  918.                (progn (c++-indent-line)
  919.                   (save-excursion
  920.                 (forward-line -1)
  921.                 (c++-indent-line))))
  922.            t)))
  923.     (progn
  924.       (if (and (memq last-command-char c++-untame-characters)
  925.            (memq (c++-in-literal bod) '(c c++)))
  926.           (insert "\\"))
  927.       ;; we need to work around a bogus feature of Emacs where an
  928.       ;; open brace at bolp means a beginning-of-defun.  but it
  929.       ;; really might not.
  930.       (and (= last-command-char ?{)
  931.            (bolp)
  932.            (c++-indent-line))
  933.       (insert last-command-char)
  934.       ;; try to clean up empty defun braces if conditions apply
  935.       (let ((here (point-marker)))
  936.         (and (memq 'empty-defun-braces c++-cleanup-list)
  937.          (c++-at-top-level-p t bod)
  938.          c++-auto-newline
  939.          (= last-command-char ?\})
  940.          (progn (forward-char -1)
  941.             (skip-chars-backward " \t\n")
  942.             (= (preceding-char) ?\{))
  943.          (not (memq (c++-in-literal) '(c c++ string)))
  944.          (delete-region (point) (1- here)))
  945.         (goto-char here)
  946.         (set-marker here nil))
  947.       (let ((here (point-marker))
  948.         mbeg mend)
  949.         (if (and (memq 'brace-else-brace c++-cleanup-list)
  950.              (= last-command-char ?\{)
  951.              (let ((status
  952.                 (re-search-backward "}[ \t\n]*else[ \t\n]*{"
  953.                         nil t)))
  954.                (setq mbeg (match-beginning 0)
  955.                  mend (match-end 0))
  956.                status)
  957.              (= mend here)
  958.              (not (memq (c++-in-literal bod) '(c c++ string))))
  959.         (progn
  960.           ;; we should clean up brace-else-brace syntax
  961.           (delete-region mbeg mend)
  962.           (insert-before-markers "} else {")
  963.           (goto-char here)
  964.           (set-marker here nil))
  965.           (goto-char here)
  966.           (set-marker here nil)))
  967.       (c++-indent-line)
  968.       (if (c++-auto-newline)
  969.           (progn
  970.         ;; c++-auto-newline may have done an auto-fill
  971.         (save-excursion
  972.           (let ((here (point-marker)))
  973.             (goto-char (- (point) 2))
  974.             (c++-indent-line)
  975.             (setq insertpos (- (goto-char here) 2))
  976.             (set-marker here nil)))
  977.         (c++-indent-line)))
  978.       (save-excursion
  979.         (if insertpos (goto-char (1+ insertpos)))
  980.         (delete-char -1))))
  981.     (if insertpos
  982.     (save-excursion
  983.       (goto-char insertpos)
  984.       (self-insert-command (prefix-numeric-value arg)))
  985.       (self-insert-command (prefix-numeric-value arg)))))
  986.  
  987. (defun c++-electric-slash (arg)
  988.   "Insert slash, and if slash is second of a double-slash comment
  989. introducing construct, indent line as comment.  This only indents if
  990. we're on a comment-only line, otherwise use `indent-for-comment' (\\[indent-for-comment])."
  991.   (interactive "P")
  992.   (let ((here (point)) char)
  993.     (self-insert-command (prefix-numeric-value arg))
  994.     (and (setq char (char-after (1- here)))
  995.      (= char ?/)
  996.      (save-excursion
  997.        (goto-char here)
  998.        (c++-indent-line)))))
  999.  
  1000. (defun c++-electric-star (arg)
  1001.   "Works with `c++-electric-slash' to auto indent C style comment lines."
  1002.   (interactive "P")
  1003.   (let ((here (point)) char)
  1004.     (self-insert-command (prefix-numeric-value arg))
  1005.     (if (and (setq char (char-after (1- here)))
  1006.          (memq (c++-in-literal) '(c))
  1007.          (memq char '(?/ ?* ?\t 32 ?\n))
  1008.          (save-excursion
  1009.            (skip-chars-backward "* \t")
  1010.            (if (= (preceding-char) ?/)
  1011.            (progn
  1012.              (forward-char -1)
  1013.              (skip-chars-backward " \t")))
  1014.            (bolp)))
  1015.     (save-excursion
  1016.       (goto-char here)
  1017.       (c++-indent-line)))))
  1018.  
  1019. (defun c++-electric-semi (arg)
  1020.   "Insert character and correct line's indentation."
  1021.   (interactive "P")
  1022.   (if (c++-in-literal)
  1023.       (self-insert-command (prefix-numeric-value arg))
  1024.     (let ((here (point-marker)))
  1025.       (if (and (memq 'defun-close-semi c++-cleanup-list)
  1026.            c++-auto-newline
  1027.            (progn
  1028.          (skip-chars-backward " \t\n")
  1029.          (= (preceding-char) ?})))
  1030.       (delete-region here (point)))
  1031.       (goto-char here)
  1032.       (set-marker here nil))
  1033.     (c++-electric-terminator arg)))
  1034.  
  1035. (defun c++-electric-colon (arg)
  1036.   "Electrify colon.
  1037. De-auto-newline double colons.  No auto-new-lines for member
  1038. initialization list."
  1039.   (interactive "P")
  1040.   (if (c++-in-literal)
  1041.       (self-insert-command (prefix-numeric-value arg))
  1042.     (let ((c++-auto-newline c++-auto-newline)
  1043.       (insertion-point (point))
  1044.       (bod (c++-point 'bod)))
  1045.       (save-excursion
  1046.     (cond
  1047.      ;; check for double-colon where the first colon is not in a
  1048.      ;; comment or literal region
  1049.      ((progn (skip-chars-backward " \t\n")
  1050.          (and (= (preceding-char) ?:)
  1051.               (not (memq (c++-in-literal bod) '(c c++ string)))))
  1052.       (progn (delete-region insertion-point (point))
  1053.          (setq c++-auto-newline nil
  1054.                insertion-point (point))))
  1055.      ;; check for ?: construct which may be at any level
  1056.      ((progn (goto-char insertion-point)
  1057.          (condition-case premature-end
  1058.              (backward-sexp 1)
  1059.            (error nil))
  1060.          ;; is possible that the sexp we just skipped was a
  1061.          ;; negative number. in that case the minus won't be
  1062.          ;; gobbled
  1063.          (skip-chars-backward "-")
  1064.          (c++-backward-syntactic-ws bod)
  1065.          (= (preceding-char) ?\?))
  1066.       (setq c++-auto-newline nil))
  1067.      ;; check for being at top level or top with respect to the
  1068.      ;; class. if not, process as normal
  1069.      ((progn (goto-char insertion-point)
  1070.          (not (c++-at-top-level-p t bod))))
  1071.      ;; if at top level, check to see if we are introducing a member
  1072.      ;; init list. if not, continue
  1073.      ((progn (c++-backward-syntactic-ws bod)
  1074.          (= (preceding-char) ?\)))
  1075.       (goto-char insertion-point)
  1076.       ;; at a member init list, figure out about auto newlining. if
  1077.       ;; nil or before then put a newline before the colon and
  1078.       ;; adjust the insertion point, but *only* if there is no
  1079.       ;; newline already before the insertion point
  1080.       (if (and (memq c++-hanging-member-init-colon '(nil before))
  1081.            c++-auto-newline)
  1082.           (if (not (save-excursion (skip-chars-backward " \t")
  1083.                        (bolp)))
  1084.           (let ((c++-auto-newline t))
  1085.             (c++-auto-newline)
  1086.             (setq insertion-point (point)))))
  1087.       ;; if hanging colon is after or nil, then newline is inserted
  1088.       ;; after colon. set up variable so c++-electric-terminator
  1089.       ;; places the newline correctly
  1090.       (setq c++-auto-newline
  1091.         (and c++-auto-newline
  1092.              (memq c++-hanging-member-init-colon '(nil after)))))
  1093.      ;; last condition is always put newline after colon
  1094.      (t (setq c++-auto-newline nil))
  1095.      ))                ; end-cond, end-save-excursion
  1096.       (goto-char insertion-point)
  1097.       (c++-electric-terminator arg))))
  1098.  
  1099. (defun c++-electric-terminator (arg)
  1100.   "Insert character and correct line's indentation."
  1101.   (interactive "P")
  1102.   (let (insertpos (end (point)))
  1103.     (if (and (not arg)
  1104.          (save-excursion
  1105.            (skip-chars-forward " \t")
  1106.            (eolp))
  1107.          (not (save-excursion
  1108.             (beginning-of-line)
  1109.             (skip-chars-forward " \t")
  1110.             (or (= (following-char) ?#)
  1111.             ;; Colon is special only after a label, or
  1112.             ;; case, or another colon.
  1113.             ;; So quickly rule out most other uses of colon
  1114.             ;; and do no indentation for them.
  1115.             (and (eq last-command-char ?:)
  1116.                  (not (looking-at "case[ \t]"))
  1117.                  (save-excursion
  1118.                    (forward-word 1)
  1119.                    (skip-chars-forward " \t")
  1120.                    (< (point) end))
  1121.                  ;; Do re-indent double colons
  1122.                  (save-excursion
  1123.                    (end-of-line 1)
  1124.                    (looking-at ":")))
  1125.             (progn
  1126.               (c++-beginning-of-defun)
  1127.               (let* ((parse-sexp-ignore-comments t)
  1128.                  (pps (parse-partial-sexp (point) end)))
  1129.                 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
  1130.     (progn
  1131.       (insert last-command-char)
  1132.       (c++-indent-line)
  1133.       (and c++-auto-newline
  1134.            (not (c++-in-parens-p))
  1135.            (progn
  1136.          ;; the new marker object, used to be just an integer
  1137.          (setq insertpos (make-marker))
  1138.          ;; changed setq to set-marker
  1139.          (set-marker insertpos (1- (point)))
  1140.          ;; do this before the newline, since in auto fill can break
  1141.          (newline)
  1142.          (c++-indent-line)))
  1143.       (save-excursion
  1144.         (if insertpos (goto-char (1+ insertpos)))
  1145.         (delete-char -1))))
  1146.     (if insertpos
  1147.     (save-excursion
  1148.       (goto-char insertpos)
  1149.       (self-insert-command (prefix-numeric-value arg)))
  1150.       (self-insert-command (prefix-numeric-value arg)))))
  1151.  
  1152. (defun c++-indent-command (&optional whole-exp)
  1153.   "Indent current line as C++ code, or in some cases insert a tab character.
  1154.  
  1155. If `c++-tab-always-indent' is t, always just indent the current line.
  1156. If nil, indent the current line only if point is at the left margin or
  1157. in the line's indentation; otherwise insert a tab.  If not-nil-or-t,
  1158. then tab is inserted only within literals (comments and strings) and
  1159. inside preprocessor directives, but line is always reindented.
  1160.  
  1161. A numeric argument, regardless of its value, means indent rigidly all
  1162. the lines of the expression starting after point so that this line
  1163. becomes properly indented.  The relative indentation among the lines
  1164. of the expression are preserved."
  1165.   (interactive "P")
  1166.   (let ((bod (c++-point 'bod)))
  1167.     (if whole-exp
  1168.     ;; If arg, always indent this line as C
  1169.     ;; and shift remaining lines of expression the same amount.
  1170.     (let ((shift-amt (c++-indent-line bod))
  1171.           beg end)
  1172.       (save-excursion
  1173.         (if (eq c++-tab-always-indent t)
  1174.         (beginning-of-line))
  1175.         (setq beg (point))
  1176.         (forward-sexp 1)
  1177.         (setq end (point))
  1178.         (goto-char beg)
  1179.         (forward-line 1)
  1180.         (setq beg (point)))
  1181.       (if (> end beg)
  1182.           (indent-code-rigidly beg end shift-amt "#")))
  1183.       (cond
  1184.        ;; CASE 1: indent when at column zero or in lines indentation,
  1185.        ;; otherwise insert a tab
  1186.        ((not c++-tab-always-indent)
  1187.     (if (and (save-excursion
  1188.            (skip-chars-backward " \t")
  1189.            (bolp))
  1190.          (or (looking-at "[ \t]*$")
  1191.              (/= (point) (c++-point 'boi))
  1192.              (bolp)))
  1193.         (c++-indent-line bod)
  1194.       (insert-tab)))
  1195.        ;; CASE 2: just indent the line
  1196.        ((eq c++-tab-always-indent t)
  1197.     (c++-indent-line bod))
  1198.        ;; CASE 3: if in a literal, insert a tab, but always indent the line
  1199.        ((or (memq (c++-in-literal bod) '(c c++ string))
  1200.         (save-excursion
  1201.           (skip-chars-backward " \t")
  1202.           (= (preceding-char) ?#)))
  1203.     (let ((here (point))
  1204.           (boi (save-excursion (back-to-indentation) (point)))
  1205.           (indent-p nil))
  1206.       (c++-indent-line bod)
  1207.       (save-excursion
  1208.         (back-to-indentation)
  1209.         (setq indent-p (and (> here boi) (= (point) boi))))
  1210.       (if indent-p (insert-tab))))
  1211.        ;; CASE 4: bogus, just indent the line
  1212.        (t (c++-indent-line bod))))))
  1213.  
  1214. (defun c++-indent-exp ()
  1215.   "Indent each line of the C++ grouping following point."
  1216.   (interactive)
  1217.   (let ((indent-stack (list nil))
  1218.     (contain-stack (list (point)))
  1219.     (case-fold-search nil)
  1220.     restart outer-loop-done inner-loop-done state ostate
  1221.     this-indent last-sexp last-depth
  1222.     at-else at-brace
  1223.     (parse-sexp-ignore-comments t)
  1224.     (opoint (point))
  1225.     (next-depth 0))
  1226.     (save-excursion
  1227.       (forward-sexp 1))
  1228.     (save-excursion
  1229.       (setq outer-loop-done nil)
  1230.       (while (and (not (eobp)) (not outer-loop-done))
  1231.     (setq last-depth next-depth)
  1232.     ;; Compute how depth changes over this line
  1233.     ;; plus enough other lines to get to one that
  1234.     ;; does not end inside a comment or string.
  1235.     ;; Meanwhile, do appropriate indentation on comment lines.
  1236.     (setq inner-loop-done nil)
  1237.     (while (and (not inner-loop-done)
  1238.             (not (and (eobp) (setq outer-loop-done t))))
  1239.       (setq ostate state)
  1240.       ;; fix by reed@adapt.net.com
  1241.       ;; must pass in the return past the end of line, so that
  1242.       ;; parse-partial-sexp finds it, and recognizes that a "//"
  1243.       ;; comment is over. otherwise, state is set that we're in a
  1244.       ;; comment, and never gets unset, causing outer-loop to only
  1245.       ;; terminate in (eobp). old:
  1246.       ;;(setq state (parse-partial-sexp (point)
  1247.       ;;(progn (end-of-line) (point))
  1248.       ;;nil nil state))
  1249.       (let ((start (point))
  1250.         (line-end
  1251.          (progn (end-of-line)
  1252.             (while (eq (c++-in-literal) 'c)
  1253.               (forward-line 1)
  1254.               (c++-indent-line)
  1255.               (end-of-line))
  1256.             (skip-chars-backward " \t")
  1257.             (end-of-line)
  1258.             (point)))
  1259.         (end (progn (if (not (eobp)) (forward-char)) (point))))
  1260.         (setq state (parse-partial-sexp start end nil nil state))
  1261.         (goto-char line-end))
  1262.       (setq next-depth (car state))
  1263.       (if (and (car (cdr (cdr state)))
  1264.            (>= (car (cdr (cdr state))) 0))
  1265.           (setq last-sexp (car (cdr (cdr state)))))
  1266.       (if (or (nth 4 ostate))
  1267.           (c++-indent-line))
  1268.       (if (or (nth 3 state))
  1269.           (forward-line 1)
  1270.         (setq inner-loop-done t)))
  1271.     (if (<= next-depth 0)
  1272.         (setq outer-loop-done t))
  1273.     (if outer-loop-done
  1274.         nil
  1275.       ;; If this line had ..))) (((.. in it, pop out of the levels
  1276.       ;; that ended anywhere in this line, even if the final depth
  1277.       ;; doesn't indicate that they ended.
  1278.       (while (> last-depth (nth 6 state))
  1279.         (setq indent-stack (cdr indent-stack)
  1280.           contain-stack (cdr contain-stack)
  1281.           last-depth (1- last-depth)))
  1282.       (if (/= last-depth next-depth)
  1283.           (setq last-sexp nil))
  1284.       ;; Add levels for any parens that were started in this line.
  1285.       (while (< last-depth next-depth)
  1286.         (setq indent-stack (cons nil indent-stack)
  1287.           contain-stack (cons nil contain-stack)
  1288.           last-depth (1+ last-depth)))
  1289.       (if (null (car contain-stack))
  1290.           (setcar contain-stack (or (car (cdr state))
  1291.                     (save-excursion (forward-sexp -1)
  1292.                             (point)))))
  1293.       (forward-line 1)
  1294.       (skip-chars-forward " \t")
  1295.       ;; check for C comment block
  1296.       (if (memq (c++-in-literal) '(c))
  1297.           (let ((eoc (save-excursion
  1298.                (re-search-forward "\\*/" (point-max) 'move)
  1299.                (point))))
  1300.         (while (< (point) eoc)
  1301.           (c++-indent-line)
  1302.           (forward-line 1))))
  1303.       (if (eolp)
  1304.           nil
  1305.         (if (and (car indent-stack)
  1306.              (>= (car indent-stack) 0))
  1307.         ;; Line is on an existing nesting level.
  1308.         ;; Lines inside parens are handled specially.
  1309.         (if (or (/= (char-after (car contain-stack)) ?{)
  1310.             ;;(c++-at-top-level-p t))
  1311.             ;; baw hack for continued statement offsets
  1312.             ;; repercussions???
  1313.             t)
  1314.             (setq this-indent (car indent-stack))
  1315.           ;; Line is at statement level.
  1316.           ;; Is it a new statement?  Is it an else?
  1317.           ;; Find last non-comment character before this line
  1318.           (save-excursion
  1319.             (setq at-else (looking-at "else\\W"))
  1320.             (setq at-brace (= (following-char) ?{))
  1321.             (c++-backward-syntactic-ws opoint)
  1322.             (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{)))
  1323.             ;; Preceding line did not end in comma or semi;
  1324.             ;; indent this line  c-continued-statement-offset
  1325.             ;; more than previous.
  1326.             (progn
  1327.               (c-backward-to-start-of-continued-exp
  1328.                (car contain-stack))
  1329.               (setq this-indent
  1330.                 (+ c-continued-statement-offset
  1331.                    (current-column)
  1332.                    (if at-brace c-continued-brace-offset 0))))
  1333.               ;; Preceding line ended in comma or semi;
  1334.               ;; use the standard indent for this level.
  1335.               (if at-else
  1336.               (progn (c++-backward-to-start-of-if opoint)
  1337.                  (back-to-indentation)
  1338.                  (skip-chars-forward "{ \t")
  1339.                  (setq this-indent (current-column)))
  1340.             (setq this-indent (car indent-stack))))))
  1341.           ;; Just started a new nesting level.
  1342.           ;; Compute the standard indent for this level.
  1343.           (let ((val (c++-calculate-indent
  1344.               (if (car indent-stack)
  1345.                   (- (car indent-stack))))))
  1346.         (setcar indent-stack
  1347.             (setq this-indent val))))
  1348.         ;; Adjust line indentation according to its contents
  1349.         (cond
  1350.          ;; looking at public, protected, private line
  1351.          ((looking-at c++-access-key)
  1352.           (setq this-indent (+ this-indent c++-access-specifier-offset)))
  1353.          ;; looking at a case, default, or other label
  1354.          ((or (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")
  1355.           (and (looking-at "[A-Za-z]")
  1356.                (save-excursion
  1357.              (forward-sexp 1)
  1358.              (looking-at ":[^:]"))))
  1359.           (setq this-indent (max 0 (+ this-indent c-label-offset))))
  1360.          ;; looking at a comment only line?
  1361.          ((looking-at comment-start-skip)
  1362.           ;; different indentation base on whether this is a col0
  1363.           ;; comment only line or not. also, if comment is in, or
  1364.           ;; to the right of comment-column, the comment doesn't
  1365.           ;; move
  1366.           (progn
  1367.         (skip-chars-forward " \t")
  1368.         (setq this-indent
  1369.               (if (>= (current-column) comment-column)
  1370.               (current-column)
  1371.             (c++-comment-offset
  1372.              (bolp)
  1373.              (+ this-indent
  1374.                 (if (save-excursion
  1375.                   (c++-backward-syntactic-ws
  1376.                    (car contain-stack))
  1377.                   (memq (preceding-char)
  1378.                     '(nil ?\, ?\; ?} ?: ?{)))
  1379.                 0 c-continued-statement-offset))
  1380.              )))))
  1381.          ;; looking at a friend declaration
  1382.          ((looking-at "friend[ \t]")
  1383.           (setq this-indent (+ this-indent c++-friend-offset)))
  1384.          ;; looking at a close brace
  1385.          ((= (following-char) ?})
  1386.           (setq this-indent (- this-indent c-indent-level)))
  1387.          ;; looking at an open brace
  1388.          ((= (following-char) ?{)
  1389.           (setq this-indent
  1390.             (+ this-indent c-brace-offset
  1391.                (if (c++-at-top-level-p t (car contain-stack))
  1392.                0 c-indent-level))))
  1393.          ;; check for continued statements
  1394.          ((save-excursion
  1395.         (c++-backward-syntactic-ws (car contain-stack))
  1396.         (and (not (c++-in-parens-p))
  1397.              (not (memq (preceding-char) '(nil ?\000 ?\; ?\} ?\: ?\{)))
  1398.              (progn
  1399.                (beginning-of-line)
  1400.                (skip-chars-forward " \t")
  1401.                (not (looking-at c++-class-key)))))
  1402.           (setq this-indent
  1403.             (+ this-indent
  1404.                c-continued-statement-offset
  1405.                ;; are we in a member init list?
  1406.                (if (not (looking-at "[ \t]*:"))
  1407.                (save-excursion
  1408.                  (let ((lim (car contain-stack)))
  1409.                    (c++-backward-syntactic-ws lim)
  1410.                    (while (and (< lim (point))
  1411.                        (= (preceding-char) ?,))
  1412.                  (beginning-of-line)
  1413.                  (c++-backward-syntactic-ws))
  1414.                    (forward-line 1)
  1415.                    (beginning-of-line)
  1416.                    (if (looking-at "[ \t]*:")
  1417.                    (- (save-excursion
  1418.                     (skip-chars-forward " \t")
  1419.                     (point))
  1420.                       (point))
  1421.                  0)))
  1422.              0)
  1423.                )))
  1424.          ;; check for stream operator
  1425.          ((looking-at "\\(<<\\|>>\\)")
  1426.           (setq this-indent (c++-calculate-indent)))
  1427.          ) ;; end-cond
  1428.         ;; Put chosen indentation into effect.
  1429.         (or (= (current-column) this-indent)
  1430.         (= (following-char) ?\#)
  1431.         (progn
  1432.           (delete-region (point) (progn (beginning-of-line) (point)))
  1433.           (indent-to this-indent)))
  1434.         ;; Indent any comment following the text.
  1435.         (or (looking-at comment-start-skip)
  1436.         (if (re-search-forward
  1437.              comment-start-skip
  1438.              (c++-point 'eol) t)
  1439.             (progn (indent-for-comment)
  1440.                (beginning-of-line))))
  1441.         ))))))
  1442.  
  1443. (defun c++-insert-header ()
  1444.   "Insert header denoting C++ code at top of buffer."
  1445.   (interactive)
  1446.   (save-excursion
  1447.     (goto-char (point-min))
  1448.     (insert "// "
  1449.         "This may look like C code, but it is really "
  1450.         "-*- C++ -*-"
  1451.         "\n\n")))
  1452.  
  1453. (defun c++-tame-comments ()
  1454.   "Backslashifies all untamed in comment regions found in the buffer.
  1455. This is a workaround for Emacs syntax bugs.  This function is
  1456. unnecessary (and un-used automatically) if you are running a patched
  1457. Emacs.  Untamed characters to escape are defined in the variable
  1458. `c++-untame-characters'."
  1459.   (interactive)
  1460.   ;; make the list into a valid charset, escaping where necessary
  1461.   (let ((charset (concat "^" (mapconcat
  1462.                   (function
  1463.                    (lambda (char)
  1464.                  (if (memq char '(?\\ ?^ ?-))
  1465.                      (concat "\\" (char-to-string char))
  1466.                    (char-to-string char))))
  1467.                   c++-untame-characters ""))))
  1468.     (save-excursion
  1469.       (beginning-of-buffer)
  1470.       (while (not (eobp))
  1471.     (skip-chars-forward charset)
  1472.     (if (and (not (zerop (following-char)))
  1473.          (memq (c++-in-literal) '(c c++))
  1474.          (/= (preceding-char) ?\\ ))
  1475.         (insert "\\"))
  1476.     (if (not (eobp))
  1477.         (forward-char 1))))))
  1478.  
  1479. ;; taken from match-paren.el. Author: unknown
  1480. (defun c++-match-paren ()
  1481.   "Jumps to the paren matching the one under point, if there is one."
  1482.   (interactive)
  1483.   (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
  1484.     (cond
  1485.      ((looking-at "[\(\[{]")
  1486.       (forward-sexp 1)
  1487.       (backward-char))
  1488.      ((looking-at "[])}]")
  1489.       (forward-char)
  1490.       (backward-sexp 1))
  1491.      (t (message "Could not find matching paren.")))))
  1492.  
  1493. (defun c++-forward-sexp (&optional arg)
  1494.   "Safe forward-sexp call."
  1495.   (interactive "p")
  1496.   (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
  1497.     (forward-sexp arg)))
  1498.  
  1499. (defun c++-backward-sexp (&optional arg)
  1500.   "Safe backward-sexp call."
  1501.   (interactive "p")
  1502.   (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
  1503.     (backward-sexp arg)))
  1504.  
  1505.  
  1506. ;; ======================================================================
  1507. ;; compatibility between emacsen
  1508. ;; ======================================================================
  1509.  
  1510. ;; This is the best we can do in vanilla GNU 18 emacsen. Note that the
  1511. ;; following problems exist:
  1512. ;; 1. We only look back to LIM, and that could place us inside a
  1513. ;;    literal if we are scanning backwards over lots of comments
  1514. ;; 2. This can potentially get slower the larger LIM is
  1515. ;; If anybody has a better solution, I'll all ears
  1516. (defun c++-backward-syntactic-ws (&optional lim)
  1517.   "Skip backwards over syntactic whitespace.
  1518. Syntactic whitespace is defined as lexical whitespace, C and C++ style
  1519. comments, and preprocessor directives.  Search no farther back than
  1520. optional LIM.  If LIM is omitted, `beginning-of-defun' is used."
  1521.   (let ((lim (or lim (c++-point 'bod)))
  1522.     literal stop)
  1523.     (if (and c++-backscan-limit
  1524.          (> (- (point) lim) c++-backscan-limit))
  1525.     (setq lim (- (point) c++-backscan-limit)))
  1526.     (while (not stop)
  1527.       (skip-chars-backward " \t\n\r\f" lim)
  1528.       ;; c++ comment
  1529.       (if (eq (setq literal (c++-in-literal lim)) 'c++)
  1530.       (progn
  1531.         (skip-chars-backward "^/" lim)
  1532.         (skip-chars-backward "/" lim)
  1533.         (while (not (or (and (= (following-char) ?/)
  1534.                  (= (char-after (1+ (point))) ?/))
  1535.                 (<= (point) lim)))
  1536.           (skip-chars-backward "^/" lim)
  1537.           (skip-chars-backward "/" lim)))
  1538.     ;; c comment
  1539.     (if (eq literal 'c)
  1540.         (progn
  1541.           (skip-chars-backward "^*" lim)
  1542.           (skip-chars-backward "*" lim)
  1543.           (while (not (or (and (= (following-char) ?*)
  1544.                    (= (preceding-char) ?/))
  1545.                   (<= (point) lim)))
  1546.         (skip-chars-backward "^*" lim)
  1547.         (skip-chars-backward "*" lim))
  1548.           (or (bobp) (forward-char -1)))
  1549.       ;; preprocessor directive
  1550.       (if (eq literal 'pound)
  1551.           (progn
  1552.         (beginning-of-line)
  1553.         (setq stop (<= (point) lim)))
  1554.         ;; just outside of c block
  1555.         (if (and (= (preceding-char) ?/)
  1556.              (= (char-after (- (point) 2)) ?*))
  1557.         (progn
  1558.           (skip-chars-backward "^*" lim)
  1559.           (skip-chars-backward "*" lim)
  1560.           (while (not (or (and (= (following-char) ?*)
  1561.                        (= (preceding-char) ?/))
  1562.                   (<= (point) lim)))
  1563.             (skip-chars-backward "^*" lim)
  1564.             (skip-chars-backward "*" lim))
  1565.           (or (bobp) (forward-char -1)))
  1566.           ;; none of the above
  1567.           (setq stop t))))))))
  1568.  
  1569. ;; This defun works well for Lemacs 19.4-7, which implemented a first
  1570. ;; shot at doing this via a C built-in backward-syntactic-ws.  This
  1571. ;; has been obsoleted in future Lemacsen and in FSF19
  1572. (defun c++-fast-backward-syntactic-ws-1 (&optional lim)
  1573.   "Skip backwards over syntactic whitespace.
  1574. Syntactic whitespace is defined as lexical whitespace, C and C++ style
  1575. comments, and preprocessor directives.  Search no farther back than
  1576. optional LIM.  If LIM is omitted, `beginning-of-defun' is used."
  1577.   (save-restriction
  1578.     (let ((parse-sexp-ignore-comments t)
  1579.       donep boi char
  1580.       (lim (or lim (c++-point 'bod))))
  1581.       (if (< lim (point))
  1582.       (unwind-protect
  1583.           (progn
  1584.         (narrow-to-region lim (point))
  1585.         ;; cpp statements are comments for our purposes here
  1586.         (if (eq major-mode 'c++-mode)
  1587.             (modify-syntax-entry ?# "< b" c++-mode-syntax-table)
  1588.           (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table)
  1589.           (modify-syntax-entry ?#  "< b" c++-c-mode-syntax-table))
  1590.         (while (not donep)
  1591.           ;; if you're not running a patched lemacs, the new byte
  1592.           ;; compiler will complain about this function. ignore that
  1593.           (backward-syntactic-ws)
  1594.           (if (not (looking-at "#\\|/\\*\\|//\\|\n"))
  1595.               (forward-char 1))
  1596.           (setq boi (c++-point 'boi)
  1597.             char (char-after boi))
  1598.           (if (and char (= char ?#))
  1599.               (progn (goto-char boi)
  1600.                  (setq donep (<= (point) lim)))
  1601.             (setq donep t))
  1602.           ))
  1603.         ;; cpp statements are not comments anywhere else.
  1604.         (if (eq major-mode 'c++-mode)
  1605.         (modify-syntax-entry ?# "." c++-mode-syntax-table)
  1606.           (modify-syntax-entry ?\n " " c++-c-mode-syntax-table)
  1607.           (modify-syntax-entry ?#  "." c++-c-mode-syntax-table))))
  1608.       )))
  1609.  
  1610. ;; This is the way it should be done for all post 19.7 Lemacsen and
  1611. ;; for all FSF19 implementations
  1612. (defun c++-fast-backward-syntactic-ws-2 (&optional lim)
  1613.   "Skip backwards over syntactic whitespace.
  1614. Syntactic whitespace is defined as lexical whitespace, C and C++ style
  1615. comments, and preprocessor directives.  Search no farther back than
  1616. optional LIM.  If LIM is omitted, `beginning-of-defun' is used."
  1617.   (save-restriction
  1618.     (let* ((lim (or lim (c++-point 'bod)))
  1619.        (here lim))
  1620.       (if (< lim (point))
  1621.       (unwind-protect
  1622.           (progn
  1623.         (narrow-to-region lim (point))
  1624.         ;; cpp statements are comments for our purposes here
  1625.         (if (eq major-mode 'c++-mode)
  1626.             (modify-syntax-entry ?# "< b" c++-mode-syntax-table)
  1627.           (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table)
  1628.           (modify-syntax-entry ?#  "< b" c++-c-mode-syntax-table))
  1629.         (while (/= here (point))
  1630.           (setq here (point))
  1631.           (forward-comment -1)))
  1632.         ;; cpp statements are not comments everywhere else
  1633.         (if (eq major-mode 'c++-mode)
  1634.         (modify-syntax-entry ?# "." c++-mode-syntax-table)
  1635.           (modify-syntax-entry ?\n " " c++-c-mode-syntax-table)
  1636.           (modify-syntax-entry ?#  "." c++-c-mode-syntax-table))))
  1637.       )))
  1638.  
  1639. ;; This is the slow and ugly way, but its the best we can do in
  1640. ;; vanilla GNU18 emacsen
  1641. (defun c++-in-literal (&optional lim)
  1642.   "Determine if point is in a C++ \"literal\".
  1643. Return `c' if in a C-style comment, `c++' if in a C++ style comment,
  1644. `string' if in a string literal, `pound' if on a preprocessor line, or
  1645. nil if not in a comment at all.  Optional LIM is used as the backward
  1646. limit of the search.  If omitted, or nil, `c++-beginning-of-defun' is
  1647. used."
  1648.   (save-excursion
  1649.     (let* ((here (point))
  1650.        (state nil)
  1651.        (match nil)
  1652.        (backlim (or lim (c++-point 'bod))))
  1653.       (goto-char backlim)
  1654.       (while (< (point) here)
  1655.     (setq match
  1656.           (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)"
  1657.                       here 'move)
  1658.            (buffer-substring (match-beginning 0) (match-end 0))))
  1659.     (setq state
  1660.           (cond
  1661.            ;; no match
  1662.            ((null match) nil)
  1663.            ;; looking at the opening of a C++ style comment
  1664.            ((string= "//" match)
  1665.         (if (<= here (progn (end-of-line) (point))) 'c++))
  1666.            ;; looking at the opening of a C block comment
  1667.            ((string= "/*" match)
  1668.         (if (not (re-search-forward "*/" here 'move)) 'c))
  1669.            ;; looking at the opening of a double quote string
  1670.            ((string= "\"" match)
  1671.         (if (not (save-restriction
  1672.                ;; this seems to be necessary since the
  1673.                ;; re-search-forward will not work without it
  1674.                (narrow-to-region (point) here)
  1675.                (re-search-forward
  1676.                 ;; this regexp matches a double quote
  1677.                 ;; which is preceded by an even number
  1678.                 ;; of backslashes, including zero
  1679.                 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
  1680.             'string))
  1681.            ;; looking at the opening of a single quote string
  1682.            ((string= "'" match)
  1683.         (if (not (save-restriction
  1684.                ;; see comments from above
  1685.                (narrow-to-region (point) here)
  1686.                (re-search-forward
  1687.                 ;; this matches a single quote which is
  1688.                 ;; preceded by zero or two backslashes.
  1689.                 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
  1690.                 here 'move)))
  1691.             'string))
  1692.            ((string-match "[ \t]*#" match)
  1693.         (if (<= here (progn (end-of-line) (point))) 'pound))
  1694.            (t nil)))
  1695.     ) ; end-while
  1696.       state)))
  1697.  
  1698. ;; This is for all 8-bit emacsen (Lucid 19, patched GNU18)
  1699. (defun c++-in-literal-8-bit (&optional lim)
  1700.   "Determine if point is in a C++ \"literal\".
  1701. Return `c' if in a C-style comment, `c++' if in a C++ style comment,
  1702. `string' if in a string literal, `pound' if on a preprocessor line, or
  1703. nil if not in a comment at all.  Optional LIM is used as the backward
  1704. limit of the search.  If omitted, or nil, `c++-beginning-of-defun' is
  1705. used."
  1706.   (save-excursion
  1707.     (let* ((backlim (or lim (c++-point 'bod)))
  1708.        (here (point))
  1709.        (parse-sexp-ignore-comments t) ; may not be necessary
  1710.        (state (parse-partial-sexp backlim (point))))
  1711.       (cond
  1712.        ((nth 3 state) 'string)
  1713.        ((nth 4 state) (if (nth 7 state) 'c++ 'c))
  1714.        ((progn
  1715.       (goto-char here)
  1716.       (beginning-of-line)
  1717.       (looking-at "[ \t]*#"))
  1718.     'pound)
  1719.        (t nil)))))
  1720.  
  1721. ;; This is for all 1-bit emacsen (FSF19)
  1722. (defun c++-in-literal-1-bit (&optional lim)
  1723.   "Determine if point is in a C++ \"literal\".
  1724. Return `c' if in a C-style comment, `c++' if in a C++ style comment,
  1725. `string' if in a string literal, `pound' if on a preprocessor line, or
  1726. nil if not in a comment at all.  Optional LIM is used as the backward
  1727. limit of the search.  If omitted, or nil, `c++-beginning-of-defun' is
  1728. used."
  1729.   (save-excursion
  1730.     (let* ((backlim (or lim (c++-point 'bod)))
  1731.        (here (point))
  1732.        (parse-sexp-ignore-comments t) ; may not be necessary
  1733.        (state (parse-partial-sexp backlim (point))))
  1734.       (cond
  1735.        ((nth 3 state) 'string)
  1736.        ((nth 4 state) (if (nth 7 state) 'c 'c++))
  1737.        ((progn
  1738.       (goto-char here)
  1739.       (beginning-of-line)
  1740.       (looking-at "[ \t]*#"))
  1741.     'pound)
  1742.        (t nil)))))
  1743.  
  1744. (cond
  1745.  ((memq 'old-v19 c++-emacs-features)
  1746.   (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-1))
  1747.  ((memq 'v19 c++-emacs-features)
  1748.   (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-2))
  1749.  )
  1750. (cond
  1751.  ((memq '8-bit c++-emacs-features)
  1752.   (fset 'c++-in-literal 'c++-in-literal-8-bit))
  1753.  ((memq '1-bit c++-emacs-features)
  1754.   (fset 'c++-in-literal 'c++-in-literal-1-bit))
  1755.  )
  1756.  
  1757.  
  1758. ;; ======================================================================
  1759. ;; defuns for parsing syntactic elements
  1760. ;; ======================================================================
  1761. (defun c++-parse-state (&optional limit)
  1762.   "Determinate the syntactic state of the code at point.
  1763. Iteratively uses `parse-partial-sexp' from point to LIMIT and returns
  1764. the result of `parse-partial-sexp' at point.  LIMIT is optional and
  1765. defaults to `point-max'."
  1766.   (let ((limit (or limit (point-max)))
  1767.     (parse-sexp-ignore-comments t)
  1768.     state)
  1769.     (while (< (point) limit)
  1770.       (setq state (parse-partial-sexp (point) limit 0)))
  1771.     state))
  1772.  
  1773. (defun c++-at-top-level-p (wrt &optional bod)
  1774.   "Return t if point is not inside a containing C++ expression, nil
  1775. if it is embedded in an expression.  When WRT is non-nil, returns nil
  1776. if not at the top level with respect to an enclosing class, or the
  1777. depth of class nesting at point.  With WRT nil, returns nil if not at
  1778. the \"real\" top level.  Optional BOD is the beginning of defun."
  1779.   (save-excursion
  1780.     (let ((indent-point (point))
  1781.       (case-fold-search nil)
  1782.       state containing-sexp paren-depth
  1783.       (bod (or bod (c++-point 'bod)))
  1784.       foundp)
  1785.       (goto-char bod)
  1786.       (setq state (c++-parse-state indent-point)
  1787.         containing-sexp (nth 1 state)
  1788.         paren-depth (nth 0 state))
  1789.       (cond
  1790.        ((eq major-mode 'c++-c-mode)
  1791.     (and (null containing-sexp) 0))
  1792.        ((not wrt)
  1793.     (null containing-sexp))
  1794.        ((null containing-sexp) 0)
  1795.        ((c++-in-parens-p) nil)
  1796.        (t
  1797.     ;; calculate depth wrt containing (possibly nested) classes
  1798.     (goto-char containing-sexp)
  1799.     (while (and (setq foundp (re-search-backward
  1800.                   (concat "[;}]\\|" c++-class-key)
  1801.                   (point-min) t))
  1802.             (let ((bod (c++-point 'bod)))
  1803.               (or (c++-in-literal bod)
  1804.               (c++-in-parens-p bod)
  1805.               ;; see if class key is inside a template spec
  1806.               (and (looking-at c++-class-key)
  1807.                    (progn (skip-chars-backward " \t\n")
  1808.                       (memq (preceding-char) '(?, ?<))))))))
  1809.     (if (memq (following-char) '(?} ?\;))
  1810.         nil
  1811.       (setq state (c++-parse-state containing-sexp))
  1812.       (and foundp
  1813.            (not (nth 1 state))
  1814.            (nth 2 state)
  1815.            paren-depth))
  1816.     )))))
  1817.  
  1818. (defun c++-in-parens-p (&optional lim)
  1819.   "Return t if inside a paren expression.
  1820. Optional LIM is used as the backward limit of the search."
  1821.   (let ((lim (or lim (c++-point 'bod))))
  1822.     (condition-case var
  1823.     (save-excursion
  1824.       (save-restriction
  1825.         (narrow-to-region (point) lim)
  1826.         (goto-char (point-max))
  1827.         (= (char-after (or (scan-lists (point) -1 1)
  1828.                    (point-min)))
  1829.            ?\()))
  1830.       (error nil)
  1831.       )))
  1832.  
  1833. (defun c++-in-function-p (&optional containing)
  1834.   "Return t if inside a C++ function definition.
  1835. Optional CONTAINING is position of containing s-exp open brace.  If not
  1836. supplied, point is used as search start."
  1837.   (save-excursion
  1838.     (let ((here (if (not containing)
  1839.             (point)
  1840.           (goto-char containing)
  1841.           (c++-backward-syntactic-ws)
  1842.           (point))))
  1843.       (if (and (= (preceding-char) ?t)
  1844.            (forward-word -1)
  1845.            (looking-at "\\<const\\>"))
  1846.       (c++-backward-syntactic-ws)
  1847.     (goto-char here))
  1848.       (= (preceding-char) ?\)))))
  1849.  
  1850.  
  1851. ;; ======================================================================
  1852. ;; defuns for calculating indentation
  1853. ;; ======================================================================
  1854. (defun c++-indent-line (&optional bod)
  1855.   "Indent current line as C++ code.
  1856. Return the amount the indentation changed by.  Optional BOD is the
  1857. point of the beginning of the C++ definition."
  1858.   (let* ((bod (or bod (c++-point 'bod)))
  1859.      (indent (c++-calculate-indent nil bod))
  1860.      beg shift-amt
  1861.      close-paren top-close-paren
  1862.      (case-fold-search nil)
  1863.      (pos (- (point-max) (point))))
  1864.     ;; calculate block close paren offset
  1865.     (if (listp c++-block-close-brace-offset)
  1866.     (setq close-paren (car c++-block-close-brace-offset)
  1867.           top-close-paren (cdr c++-block-close-brace-offset))
  1868.       (setq close-paren c++-block-close-brace-offset
  1869.         top-close-paren c++-block-close-brace-offset))
  1870.     ;; now start cleanup
  1871.     (beginning-of-line)
  1872.     (setq beg (point))
  1873.     (cond
  1874.      ((eq indent nil)
  1875.       (setq indent (current-indentation)))
  1876.      ((eq indent t)
  1877.       (setq indent (c++-calculate-c-indent-within-comment)))
  1878.      ((looking-at "[ \t]*#")
  1879.       (setq indent 0))
  1880.      ((save-excursion
  1881.     (back-to-indentation)
  1882.     (looking-at "//\\|/\\*"))
  1883.       ;; we've found a comment-only line. we now must try to determine
  1884.       ;; if the line is a continuation from a comment on the previous
  1885.       ;; line.  we check to see if the comment starts in or to the
  1886.       ;; right of comment-column and if so, we don't change its
  1887.       ;; indentation.
  1888.       (skip-chars-forward " \t")
  1889.       (if (>= (current-column) comment-column)
  1890.       (setq indent (current-column))
  1891.     (setq indent (c++-comment-offset (bolp) indent))))
  1892.      (t
  1893.       (skip-chars-forward " \t")
  1894.       (if (listp indent) (setq indent (car indent)))
  1895.       (cond
  1896.        ((looking-at c++-access-key)
  1897.     (setq indent (+ indent c++-access-specifier-offset)))
  1898.        ((looking-at "default[ \t]*:")
  1899.     (setq indent (+ indent c-label-offset)))
  1900.        ((or (looking-at "case[ \t]+.*:")
  1901.         (and (looking-at "[A-Za-z]")
  1902.          (save-excursion
  1903.            (forward-sexp 1)
  1904.            (looking-at ":[^:]"))))
  1905.     (setq indent (max 1 (+ indent c-label-offset))))
  1906.        ((and (looking-at "else\\b")
  1907.          (not (looking-at "else\\s_")))
  1908.     (setq indent (save-excursion
  1909.                (c++-backward-to-start-of-if)
  1910.                (back-to-indentation)
  1911.                (skip-chars-forward "{ \t")
  1912.                (current-column))))
  1913.        ((looking-at "\\<friend\\>")
  1914.     (setq indent (+ indent c++-friend-offset)))
  1915.        ((and (= (following-char) ?\))
  1916.          c++-paren-as-block-close-p)
  1917.     (setq indent (+ (- indent c-indent-level)
  1918.             (if (save-excursion
  1919.                   (forward-char 1)
  1920.                   (c++-at-top-level-p nil bod))
  1921.                 top-close-paren
  1922.               close-paren))))
  1923.        ((= (following-char) ?})
  1924.     (setq indent (+ (- indent c-indent-level)
  1925.             (if (save-excursion
  1926.                   (forward-char 1)
  1927.                   (c++-at-top-level-p nil bod))
  1928.                 top-close-paren
  1929.               close-paren))))
  1930.        ((= (following-char) ?{)
  1931.     (setq indent (+ indent c-brace-offset))))))
  1932.     (skip-chars-forward " \t")
  1933.     (setq shift-amt (- indent (current-column)))
  1934.     (if (zerop shift-amt)
  1935.     (if (> (- (point-max) pos) (point))
  1936.         (goto-char (- (point-max) pos)))
  1937.       (delete-region beg (point))
  1938.       (indent-to indent)
  1939.       ;; If initial point was within line's indentation,
  1940.       ;; position after the indentation.  Else stay at same point in text.
  1941.       (if (> (- (point-max) pos) (point))
  1942.       (goto-char (- (point-max) pos))))
  1943.     ;; save-excursion is necessary because things break if the hook
  1944.     ;; changes point or mark
  1945.     (save-excursion
  1946.       (run-hooks 'c++-special-indent-hook))
  1947.     shift-amt))
  1948.  
  1949. (defun c++-cont-indent (ipnt char lim)
  1950.   "Calculate the indentation for a continued statement.
  1951. IPNT is the indentation point; CHAR is the character before the
  1952. indentation point, excluding any intervening whitespace; LIM is the
  1953. minimum point to search backwards to."
  1954.   (let ((charlist '(nil ?\000 ?\, ?\; ?\} ?\: ?\{))
  1955.     streamop-pos here)
  1956.     (goto-char ipnt)
  1957.     (c++-backward-syntactic-ws lim)
  1958.     (if (not (memq char charlist))
  1959.     ;; This line is continuation of preceding line's statement
  1960.     (progn
  1961.       (c-backward-to-start-of-continued-exp lim)
  1962.       ;; take care of << and >> while in streams
  1963.       (setq here (point))
  1964.       (if (save-excursion
  1965.         (and (progn (goto-char ipnt)
  1966.                 (looking-at "[ \t]*\\(<<\\|>>\\)"))
  1967.              (progn (goto-char here)
  1968.                 (skip-chars-forward "^><\n")
  1969.                 (setq streamop-pos (current-column))
  1970.                 (looking-at "\\(<<\\|>>\\)"))))
  1971.           streamop-pos
  1972.         (+ (current-column)
  1973.            ;; prevent repeated continued indentation
  1974.            (if (save-excursion
  1975.              (beginning-of-line 1)
  1976.              (c++-backward-syntactic-ws lim)
  1977.              (memq (preceding-char) charlist))
  1978.            c-continued-statement-offset
  1979.          ;; the following statements *do* indent even
  1980.          ;; for single statements (are there others?)
  1981.          (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b")
  1982.              c-continued-statement-offset
  1983.            ;; else may be a continued statement inside
  1984.            ;; a simple for/else/while/if/do loop
  1985.            (beginning-of-line 1)
  1986.            (forward-char -1)
  1987.            (c++-backward-syntactic-ws lim)
  1988.            (c-backward-to-start-of-continued-exp lim)
  1989.            (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b")
  1990.                c-continued-statement-offset
  1991.              0)))
  1992.            (save-excursion
  1993.          (goto-char ipnt)
  1994.          (skip-chars-forward " \t")
  1995.          (cond
  1996.           ((= (following-char) ?\{)
  1997.            c-continued-brace-offset)
  1998.           ((and (= (following-char) ?\})
  1999.             (progn (forward-char 1)
  2000.                    (c++-at-top-level-p nil lim)))
  2001.            (- c-continued-statement-offset))
  2002.           (t 0))))))
  2003.       nil)))
  2004.  
  2005. (defun c++-calculate-indent (&optional parse-start bod)
  2006.   "Return appropriate indentation for current line as C++ code.
  2007. In usual case returns an integer: the column to indent to.
  2008. Returns nil if line starts inside a string, t if in a comment.
  2009. Optional PARSE-START is the location to start parsing, and optional
  2010. BOD is the beginning of the C++ definition."
  2011.   (save-excursion
  2012.     (beginning-of-line)
  2013.     (let ((indent-point (point))
  2014.       (case-fold-search nil)
  2015.       state do-indentation literal in-meminit-p
  2016.       containing-sexp streamop-pos char-before-ip
  2017.       (inclass-shift 0) inclass-depth inclass-unshift
  2018.       (bod (or bod (c++-point 'bod))))
  2019.       (if parse-start
  2020.       (goto-char parse-start)
  2021.     (goto-char bod))
  2022.       (setq parse-start (point)
  2023.         state (c++-parse-state indent-point)
  2024.         containing-sexp (nth 1 state))
  2025.       ;; it is possible that c++-defun-header-weak could not find the
  2026.       ;; beginning of the C++ definition. The following code attempts
  2027.       ;; to work around this.  It is probably better to just use
  2028.       ;; c++-match-header-strongly, but there are performance questions
  2029.       (if (null state)
  2030.       (let* ((c++-match-header-strongly t)
  2031.          (bod (c++-point 'bod)))
  2032.         (goto-char bod)
  2033.         (setq state (c++-parse-state indent-point)
  2034.           containing-sexp (nth 1 state)
  2035.           parse-start (point))))
  2036.       (setq literal (c++-in-literal bod))
  2037.       ;; cache char before indent point
  2038.       (save-excursion
  2039.     (goto-char indent-point)
  2040.     (c++-backward-syntactic-ws bod)
  2041.     (setq char-before-ip (preceding-char)))
  2042.       (cond
  2043.        ;; CASE 1: in a string.
  2044.        ((memq literal '(string)) nil)
  2045.        ;; CASE 2: in a C or C++ style comment.
  2046.        ((memq literal '(c c++)) t)
  2047.        ;; CASE 3: Line is at top level.  May be comment-only line,
  2048.        ;; data or function definition, or may be function argument
  2049.        ;; declaration or member initialization.  Indent like the
  2050.        ;; previous top level line unless:
  2051.        ;;
  2052.        ;; 1. the previous line ends in a closeparen without
  2053.        ;; semicolon, in which case this line is the first
  2054.        ;; argument declaration or member initialization, or
  2055.        ;;
  2056.        ;; 2. the previous line ends with a closeparen
  2057.        ;; (closebrace), optional spaces, and a semicolon, in
  2058.        ;; which case this line follows a multiline function
  2059.        ;; declaration (class definition), or
  2060.        ;;
  2061.        ;; 3. the previous line begins with a colon, in which
  2062.        ;; case this is the second line of member inits.  It is
  2063.        ;; assumed that arg decls and member inits are not mixed.
  2064.        ;;
  2065.        ((setq inclass-depth (c++-at-top-level-p t bod))
  2066.     (+
  2067.      ;; add an offset if we are inside a class defun body, i.e. we
  2068.      ;; are at the top level, but only wrt a containing class
  2069.      (let ((shift/level (+ c-indent-level c-brace-imaginary-offset)))
  2070.        (setq inclass-shift (* shift/level inclass-depth)
  2071.          inclass-unshift (* shift/level (max 0 (1- inclass-depth))))
  2072.        inclass-shift)
  2073.      (progn
  2074.        (goto-char indent-point)
  2075.        (skip-chars-forward " \t")
  2076.        (cond
  2077.         ;;
  2078.         ((or (= (following-char) ?{)
  2079.          (progn
  2080.            (c++-backward-syntactic-ws parse-start)
  2081.            (bobp)))
  2082.          0)
  2083.         ;; first arg decl or member init
  2084.         ((c++-in-function-p)
  2085.          (goto-char indent-point)
  2086.          (skip-chars-forward " \t")
  2087.          (if (= (following-char) ?:)
  2088.          c++-member-init-indent
  2089.            c-argdecl-indent))
  2090.         ;;
  2091.         ((progn
  2092.            (if (= (preceding-char) ?\;)
  2093.            (progn
  2094.              (backward-char 1)
  2095.              (skip-chars-backward " \t")))
  2096.            ;; may be first line after a hanging member init colon.
  2097.            ;; check to be sure its not a scope operator meaning we
  2098.            ;; are inside a member def
  2099.            (or (= (preceding-char) ?:)
  2100.            (save-excursion
  2101.              (forward-line 1)
  2102.              (skip-chars-forward " \t")
  2103.              (or (eobp) (forward-char 1))
  2104.              (and (= (preceding-char) ?:)
  2105.               (/= (following-char) ?:)))
  2106.            (save-excursion
  2107.              (and (= (preceding-char) ?,)
  2108.               (let ((bol (c++-point 'bol)))
  2109.                 (skip-chars-backward "^:" bol)
  2110.                 (= (preceding-char) ?:))
  2111.               (not (c++-in-parens-p))
  2112.               (progn
  2113.                 (forward-char -1)
  2114.                 (skip-chars-backward " \t")
  2115.                 (not (bolp)))
  2116.               ;; make sure its not a multiple inheritance
  2117.               ;; continuation line
  2118.               (progn
  2119.                 (beginning-of-line)
  2120.                 (not (looking-at c++-inher-key)))
  2121.               ))))
  2122.          ;; check to see if we're looking at a member init, or
  2123.          ;; access specifier
  2124.          (if (progn
  2125.            (beginning-of-line)
  2126.            (skip-chars-forward " \t")
  2127.            (looking-at c++-access-key))
  2128.          ;; access specifier. class defun opening brace may
  2129.          ;; not be in col zero, and derived classes could be
  2130.          ;; on a separate line than class intro
  2131.          (progn
  2132.            (goto-char (or containing-sexp bod))
  2133.            (beginning-of-line)
  2134.            (skip-chars-forward " \t")
  2135.            (if (looking-at
  2136.             ":[ \t]*\\<\\(public\\|protected\\|private\\)\\>")
  2137.                (forward-line -1))
  2138.            (- (current-indentation)
  2139.               ;; remove some nested inclass indentation
  2140.               inclass-unshift))
  2141.            ;; member init, so add offset. add additional offset if
  2142.            ;; looking at line with just a member init colon
  2143.            (+ c++-member-init-indent
  2144.           (if (looking-at ":[ \t]*$")
  2145.               (or c++-continued-member-init-offset 0) 0))))
  2146.         ((or (= (preceding-char) ?})
  2147.          (= (preceding-char) ?\))
  2148.          (save-excursion
  2149.            (beginning-of-line)
  2150.            (looking-at "[ \t]*\\<friend\\>")))
  2151.          ;; indentation of class defun opening brace may not be
  2152.          ;; zero
  2153.          (goto-char (or containing-sexp bod))
  2154.          (- (current-indentation)
  2155.         ;; remove some nested inclass indentation
  2156.         inclass-unshift))
  2157.         ;; cont arg decls or member inits.  we might be inside a
  2158.         ;; K&R C arg decl
  2159.         ((save-excursion
  2160.            (while (and (< bod (point))
  2161.                (memq (preceding-char) '(?\, ?\;)))
  2162.          (beginning-of-line)
  2163.          (c++-backward-syntactic-ws bod))
  2164.            (and (eq major-mode 'c++-c-mode)
  2165.             (= (preceding-char) ?\))))
  2166.          (+ c-argdecl-indent
  2167.         (progn
  2168.           (goto-char indent-point)
  2169.           (c++-backward-syntactic-ws bod)
  2170.           (if (= (preceding-char) ?,)
  2171.               c-continued-statement-offset
  2172.             0))))
  2173.         ((progn
  2174.            (beginning-of-line)
  2175.            (skip-chars-forward " \t")
  2176.            (or (memq (c++-in-literal bod) '(c c++))
  2177.            (looking-at "/[/*]")))
  2178.          0)
  2179.         ;; are we looking at the first member init?
  2180.         ((and (= (following-char) ?:)
  2181.           (save-excursion
  2182.             (c++-backward-syntactic-ws bod)
  2183.             (= (preceding-char) ?\))))
  2184.          (if c++-continued-member-init-offset
  2185.          (+ (current-indentation)
  2186.             c++-continued-member-init-offset)
  2187.            (progn
  2188.          (forward-char 1)
  2189.          (skip-chars-forward " \t")
  2190.          (- (current-column)
  2191.             inclass-shift))))
  2192.         ;; else first check to see if its a multiple inheritance
  2193.         ;; continuation line, but not a K&R C arg decl
  2194.         ((and (not (eq major-mode 'c++-c-mode))
  2195.           (looking-at c++-inher-key))
  2196.          (if (= char-before-ip ?,)
  2197.          (progn (goto-char (match-end 0))
  2198.             (current-column))
  2199.            ;; nope, its probably a nested class
  2200.            0))
  2201.         ;; we might be looking at the opening brace of a class
  2202.         ;; defun
  2203.         ((= (following-char) ?\{)
  2204.          ;; indentation of opening brace may not be zero
  2205.          (- (current-indentation)
  2206.         ;; remove some nested inclass indentation
  2207.         inclass-unshift))
  2208.         ((eolp)
  2209.          ;; looking at a blank line, indent next line to zero
  2210.          0)
  2211.         ;; at beginning of buffer, if nothing else, indent to zero
  2212.         ((save-excursion
  2213.            (goto-char indent-point)
  2214.            (beginning-of-line)
  2215.            (bobp))
  2216.          0)
  2217.         ;; this could be a compound statement, but make sure its
  2218.         ;; not a member init list
  2219.         ((save-excursion
  2220.            (goto-char indent-point)
  2221.            (c++-backward-syntactic-ws bod)
  2222.            (and (= (preceding-char) ?,)
  2223.             (save-excursion
  2224.               (while (and (< bod (point))
  2225.                   (= (preceding-char) ?,))
  2226.             (beginning-of-line)
  2227.             (c++-backward-syntactic-ws bod))
  2228.               (forward-line 1)
  2229.               (not (setq in-meminit-p (looking-at "[ \t]*:"))))))
  2230.          c-continued-statement-offset)
  2231.         (t
  2232.          (if (c++-in-parens-p)
  2233.          ;; we are perhaps inside a member init call
  2234.          (while (and (c++-in-parens-p)
  2235.                  (< bod (point)))
  2236.            (forward-line -1)
  2237.            (skip-chars-forward " \t")))
  2238.          ;; check to be sure that we're not on the first line of
  2239.          ;; the member init list
  2240.          (if (and (= (following-char) ?:)
  2241.               (save-excursion
  2242.             (c++-backward-syntactic-ws bod)
  2243.             (= (preceding-char) ?\))))
  2244.          (progn
  2245.            (forward-char 1)
  2246.            (skip-chars-forward " \t")))
  2247.          ;; skip to start of compound statement, but only if we're
  2248.          ;; not in a member initialization list
  2249.          (if (not in-meminit-p)
  2250.          (let ((ipnt (point)))
  2251.            (c++-backward-syntactic-ws bod)
  2252.            (while (and (= (preceding-char) ?,)
  2253.                    (< bod (point)))
  2254.              (beginning-of-line)
  2255.              (skip-chars-forward " \t")
  2256.              (setq ipnt (point))
  2257.              (c++-backward-syntactic-ws bod))
  2258.            (goto-char ipnt)))
  2259.          ;; subtract inclass-shift since its already incorporated
  2260.          ;; by default in current-column
  2261.          (- (current-column) inclass-shift)
  2262.          )))))
  2263.        ;; CASE 4: line is expression, not statement. indent to just
  2264.        ;; after the surrounding open -- unless empty arg list, in
  2265.        ;; which case we do what c++-empty-arglist-indent says to do.
  2266.        ((/= (char-after containing-sexp) ?{)
  2267.     (if (and c++-empty-arglist-indent
  2268.          (or c++-always-arglist-indent-p
  2269.              (null (nth 2 state))
  2270.              ;; indicates empty arg list.  Use a heuristic: if
  2271.              ;; the first non-whitespace following left paren
  2272.              ;; on same line is not a comment, is not an empty
  2273.              ;; arglist.
  2274.              (save-excursion
  2275.                (goto-char (1+ containing-sexp))
  2276.                (looking-at "[ \t]*[/\n]"))))
  2277.         (progn
  2278.           (goto-char containing-sexp)
  2279.           (beginning-of-line)
  2280.           (skip-chars-forward " \t")
  2281.           (goto-char (min (+ (point) c++-empty-arglist-indent)
  2282.                   (1+ containing-sexp)))
  2283.           (current-column))
  2284.       ;; In C-mode, we would always indent to one after the
  2285.       ;; left paren.  Here, though, we may have an
  2286.       ;; empty-arglist, so we'll indent to the min of that
  2287.       ;; and the beginning of the first argument.
  2288.       (goto-char (1+ containing-sexp))
  2289.       ;; We want to skip any whitespace b/w open paren and
  2290.       ;; first argument. this handles while (thing) style
  2291.       ;; and while( thing ) style
  2292.       (skip-chars-forward " \t")
  2293.       (current-column)))
  2294.        ;; CASE 5: Statement.  Find previous non-comment character.
  2295.        (t
  2296.     (or (c++-cont-indent indent-point char-before-ip containing-sexp)
  2297.       ;; This line may start a new statement, or it could
  2298.       ;; represent the while closure of a do/while construct
  2299.       (if (save-excursion
  2300.         (and (progn (goto-char indent-point)
  2301.                 (skip-chars-forward " \t\n")
  2302.                 (looking-at "while\\b"))
  2303.              (progn
  2304.                (c++-backward-to-start-of-do containing-sexp)
  2305.                (looking-at "do\\b"))
  2306.              (setq do-indentation (current-column))))
  2307.           do-indentation
  2308.         ;; this could be a case statement. if so we want to
  2309.         ;; indent it like the first case statement after a switch
  2310.         (if (save-excursion
  2311.           (goto-char indent-point)
  2312.           (skip-chars-forward " \t\n")
  2313.           (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):"))
  2314.         (progn
  2315.           (goto-char containing-sexp)
  2316.           (back-to-indentation)
  2317.           (+ (current-column) c-indent-level))
  2318.           ;; else, this is the start of a new statement
  2319.           ;; Position following last unclosed open.
  2320.           (goto-char containing-sexp)
  2321.           ;; Is line first statement after an open-brace?
  2322.           (or
  2323.            (and c++-relative-offset-p
  2324.             ;; If no, find that first statement and
  2325.             ;; indent like it.
  2326.             (save-excursion
  2327.               (forward-char 1)
  2328.               (while
  2329.               (progn
  2330.                 (skip-chars-forward " \t\n")
  2331.                 (looking-at
  2332.                  (concat
  2333.                   "#\\|/\\*\\|//"
  2334.                   "\\|\\(case[ \t]+.*\\|default[ \t]*\\):"
  2335.                   "\\|[a-zA-Z0-9_$]*:[^:]"
  2336.                   "\\|friend[ \t]"
  2337.                   c++-class-key
  2338.                   "[ \t]")))
  2339.             ;; Skip over comments and labels
  2340.             ;; following openbrace.
  2341.             (cond
  2342.              ((= (following-char) ?\#)
  2343.               (forward-line 1))
  2344.              ((looking-at "/\\*")
  2345.               (search-forward "*/" nil 'move))
  2346.              ((looking-at
  2347.                (concat "//\\|friend[ \t]" c++-class-key
  2348.                    "[ \t]"))
  2349.               (forward-line 1))
  2350.              ((looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")
  2351.               (forward-line 1))
  2352.              (t
  2353.               (re-search-forward ":[^:]" nil 'move))))
  2354.               ;; The first following code counts
  2355.               ;; if it is before the line we want to indent.
  2356.               (and (< (point) indent-point)
  2357.                (+ (current-column)
  2358.                   (c++-compound-offset
  2359.                    char-before-ip containing-sexp bod)))))
  2360.            ;; If no previous statement, indent it relative to
  2361.            ;; line brace is on.  For open brace in column
  2362.            ;; zero, don't let statement start there too.  If
  2363.            ;; c-indent-offset is zero, use c-brace-offset +
  2364.            ;; c-continued-statement-offset instead.  For
  2365.            ;; open-braces not the first thing in a line, add
  2366.            ;; in c-brace-imaginary-offset.
  2367.            (+ (if (and (bolp) (zerop c-indent-level))
  2368.               (+ c-brace-offset c-continued-statement-offset)
  2369.             c-indent-level)
  2370.           ;; Move back over whitespace before the openbrace.
  2371.           ;; If openbrace is not first nonwhite thing on the line,
  2372.           ;; add the c-brace-imaginary-offset.
  2373.           (progn (skip-chars-backward " \t")
  2374.              (if (bolp) 0 c-brace-imaginary-offset))
  2375.           ;; If the openbrace is preceded by a parenthesized exp,
  2376.           ;; move to the beginning of that;
  2377.           ;; possibly a different line
  2378.           (progn
  2379.             (if (eq (preceding-char) ?\))
  2380.             (forward-sexp -1))
  2381.             ;; Get initial indentation of the line we are on.
  2382.             (current-indentation)))))))) ; end t outer cond
  2383.        ))))
  2384.  
  2385. (defun c++-calculate-c-indent-within-comment ()
  2386.   "Return the indentation amount for line, assuming that
  2387. the current line is to be regarded as part of a block comment."
  2388.   (let (end stars indent)
  2389.     (save-excursion
  2390.       (beginning-of-line)
  2391.       (skip-chars-forward " \t")
  2392.       (setq stars (if (looking-at "\\*\\*?")
  2393.               (- (match-end 0) (match-beginning 0))
  2394.             0))
  2395.       (skip-chars-backward " \t\n")
  2396.       (setq end (point))
  2397.       (beginning-of-line)
  2398.       (skip-chars-forward " \t")
  2399.       (if (re-search-forward "/\\*[ \t]*" end t)
  2400.       (goto-char (+ (match-beginning 0)
  2401.             (cond
  2402.              (c++-C-block-comments-indent-p 0)
  2403.              ((= stars 1) 1)
  2404.              ((= stars 2) 0)
  2405.              (t (- (match-end 0) (match-beginning 0)))))))
  2406.       (current-column))))
  2407.  
  2408. (defun c++-comment-offset (col0-line-p indent)
  2409.   "Calculates and returns the comment-only line offset.
  2410. Offset is based on the value of `c++-comment-only-line-offset', the
  2411. argument COL0-LINE-P, and the current indentation INDENT."
  2412.   (let ((offset 0))
  2413.     (if col0-line-p
  2414.     ;; col0 means we need to look at the second member of the var's
  2415.     ;; list value. if value is not a list, then zero is used
  2416.     (if (listp c++-comment-only-line-offset)
  2417.         ;; it is a list, so second element must be nil or a number
  2418.         (setq offset
  2419.           (+ indent
  2420.              (or (car (cdr c++-comment-only-line-offset))
  2421.              (car c++-comment-only-line-offset)))))
  2422.       ;; not in column zero so indentation is car or value of variable
  2423.       (setq offset
  2424.         (+ indent
  2425.            (if (listp c++-comment-only-line-offset)
  2426.            (car c++-comment-only-line-offset)
  2427.          c++-comment-only-line-offset))))
  2428.     offset))
  2429.  
  2430. (defun c++-compound-offset (char-before-ip containing-sexp bod)
  2431.   "Calculates any addition offset due a comma separated compound statement.
  2432. CHAR-BEFORE-IP is the character before the indentation point and
  2433. CONTAINING-SEXP is the buffer position of the open brace or paren.
  2434. BOD is the `beginning-of-defun' point."
  2435.   (cond
  2436.    ;; not a compound statement
  2437.    ((/= char-before-ip ?,) 0)
  2438.    ;; open brace could be at column zero == bod
  2439.    ((and (= containing-sexp bod)
  2440.      (or (let ((lim (progn
  2441.               (goto-char containing-sexp)
  2442.               (forward-line -1)
  2443.               (point))))
  2444.            (end-of-line)
  2445.            (c++-backward-syntactic-ws lim)
  2446.            (= (preceding-char) ?=))
  2447.          (progn
  2448.            (beginning-of-line)
  2449.            (looking-at "\\(^\\|[ \t]*\\)enum[ \t]"))
  2450.          ))
  2451.     0)
  2452.    ;; check for inside an enum
  2453.    ((let ((parse-sexp-ignore-comments t)
  2454.       in-enum-p)
  2455.       (goto-char containing-sexp)
  2456.       (while (< bod (point))
  2457.     (c++-backward-syntactic-ws)
  2458.     (if (memq (preceding-char) '(?\) ?\" ?\; ?\}))
  2459.         (goto-char bod)
  2460.       (forward-sexp -1)
  2461.       (if (looking-at "\\(enum[ \t\n]\\|\\[.*\\]\\)")
  2462.           (progn (goto-char bod)
  2463.              (setq in-enum-p t)))))
  2464.       in-enum-p)
  2465.     0)
  2466.    ;; assume we're not in a list of enums or static array elems
  2467.    (t c-continued-statement-offset)
  2468.    ))
  2469.    
  2470.  
  2471.  
  2472. ;; ======================================================================
  2473. ;; defuns to look backwards for things
  2474. ;; ======================================================================
  2475.  
  2476. (defun c++-backward-to-start-of-do (&optional limit)
  2477.   "Move to the start of the last \"unbalanced\" do."
  2478.   (let ((do-level 1)
  2479.     (case-fold-search nil)
  2480.     (limit (or limit (c++-point 'bod))))
  2481.     (while (not (zerop do-level))
  2482.       ;; we protect this call because trying to execute this when the
  2483.       ;; while is not associated with a do will throw an error
  2484.       (condition-case err
  2485.       (progn
  2486.         (backward-sexp 1)
  2487.         (cond
  2488.          ((memq (c++-in-literal limit) '(c c++)))
  2489.          ((looking-at "while\\b")
  2490.           (setq do-level (1+ do-level)))
  2491.          ((looking-at "do\\b")
  2492.           (setq do-level (1- do-level)))
  2493.          ((< (point) limit)
  2494.           (setq do-level 0)
  2495.           (goto-char limit))))
  2496.     (error
  2497.      (goto-char limit)
  2498.      (setq do-level 0))))))
  2499.  
  2500. (defun c++-backward-to-start-of-if (&optional limit)
  2501.   "Move to the start of the last \"unbalanced\" if."
  2502.   (let ((if-level 1)
  2503.     (case-fold-search nil)
  2504.     (limit (or limit (c++-point 'bod))))
  2505.     (while (and (not (bobp))
  2506.         (not (zerop if-level)))
  2507.       (c++-backward-syntactic-ws)
  2508.       (c++-backward-sexp 1)
  2509.       (cond ((looking-at "else\\b")
  2510.          (setq if-level (1+ if-level)))
  2511.         ((looking-at "if\\b")
  2512.          (setq if-level (1- if-level)))
  2513.         ((< (point) limit)
  2514.          (setq if-level 0)
  2515.          (goto-char limit))))))
  2516.  
  2517. (defun c++-auto-newline ()
  2518.   "Insert a newline iff we're not in a literal.
  2519. Literals are defined as being inside a C or C++ style comment or open
  2520. string according to mode's syntax."
  2521.   (let ((bod (c++-point 'bod)))
  2522.     (and c++-auto-newline
  2523.      (not (c++-in-literal bod))
  2524.      (not (newline)))))
  2525.  
  2526. (defun c++-point (position)
  2527.   "Returns the value of point at certain commonly referenced POSITIONs.
  2528. POSITION can be one of the following symbols:
  2529.   `bol' -- beginning of line
  2530.   `eol' -- end of line
  2531.   `bod' -- beginning of defun
  2532.   `boi' -- back to indentation
  2533. This function does not modify point or mark."
  2534.   (let ((here (point)) bufpos)
  2535.     (cond
  2536.      ((eq position 'bol) (beginning-of-line))
  2537.      ((eq position 'eol) (end-of-line))
  2538.      ((eq position 'bod) (c++-beginning-of-defun))
  2539.      ((eq position 'boi) (back-to-indentation))
  2540.      )
  2541.     (setq bufpos (point))
  2542.     (goto-char here)
  2543.     bufpos))
  2544.  
  2545.  
  2546. ;; ======================================================================
  2547. ;; defuns for "macroizations" -- making C++ parameterized types via macros
  2548. ;; ======================================================================
  2549. (defun c++-macroize-region (from to arg)
  2550.   "Insert backslashes at end of every line in region.
  2551. Useful for defining cpp macros.  If called with a prefix argument,
  2552. it will remove trailing backslashes."
  2553.   (interactive "r\nP")
  2554.   (save-excursion
  2555.     (goto-char from)
  2556.     (beginning-of-line 1)
  2557.     (let ((line (count-lines (point-min) (point)))
  2558.       (to-line (save-excursion (goto-char to)
  2559.                    (count-lines (point-min) (point)))))
  2560.       (while (< line to-line)
  2561.     (c++-backslashify-current-line (null arg))
  2562.     (forward-line 1) (setq line (1+ line))))))
  2563.  
  2564. (defun c++-backslashify-current-line (doit)
  2565.   "Backslashifies current line."
  2566.   (end-of-line 1)
  2567.   (cond
  2568.    (doit
  2569.     ;; Note that "\\\\" is needed to get one backslash.
  2570.     (if (not (save-excursion (forward-char -1) (looking-at "\\\\")))
  2571.     (progn
  2572.       (if (>= (current-column) c++-default-macroize-column)
  2573.           (insert " \\")
  2574.         (while (<= (current-column) c++-default-macroize-column)
  2575.           (insert "\t") (end-of-line))
  2576.         (delete-char -1)
  2577.         (while (< (current-column) c++-default-macroize-column)
  2578.           (insert " ") (end-of-line))
  2579.         (insert "\\")))))
  2580.    (t
  2581.     (forward-char -1)
  2582.     (if (looking-at "\\\\")
  2583.     (progn (skip-chars-backward " \t")
  2584.            (kill-line))))))
  2585.  
  2586.  
  2587. ;; ======================================================================
  2588. ;; defuns for  commenting out multiple lines.
  2589. ;; ======================================================================
  2590. (defun c++-comment-region (beg end)
  2591.   "Comment out all lines in a region between mark and current point by
  2592. inserting `comment-start' in front of each line."
  2593.   (interactive "*r")
  2594.   (save-excursion
  2595.     (save-restriction
  2596.       (narrow-to-region
  2597.        (progn (goto-char beg) (beginning-of-line) (point))
  2598.        (progn (goto-char end) (or (bolp) (forward-line 1)) (point)))
  2599.       (goto-char (point-min))
  2600.       (while (not (eobp))
  2601.     (insert comment-start)
  2602.     (forward-line 1))
  2603.       (if (eq major-mode 'c++-c-mode)
  2604.       (insert comment-end)))))
  2605.  
  2606. (defun c++-uncomment-region (beg end)
  2607.   "Uncomment all lines in region between mark and current point by deleting
  2608. the leading `// ' from each line, if any."
  2609.   (interactive "*r")
  2610.   (save-excursion
  2611.     (save-restriction
  2612.       (narrow-to-region
  2613.        (progn (goto-char beg) (beginning-of-line) (point))
  2614.        (progn (goto-char end) (forward-line 1) (point)))
  2615.       (goto-char (point-min))
  2616.       (let ((comment-regexp
  2617.          (if (eq major-mode 'c++-c-mode)
  2618.          (concat "\\s *\\(" (regexp-quote comment-start)
  2619.              "\\|"      (regexp-quote comment-end)
  2620.              "\\)")
  2621.            (concat "\\s *" (regexp-quote comment-start)))))
  2622.     (while (not (eobp))
  2623.       (if (looking-at comment-regexp)
  2624.           (delete-region (match-beginning 0) (match-end 0)))
  2625.       (forward-line 1))))))
  2626.  
  2627.  
  2628. ;; ======================================================================
  2629. ;; grammar parsing
  2630. ;; ======================================================================
  2631.  
  2632. ;;; Below are two regular expressions that attempt to match defuns
  2633. ;;; "strongly" and "weakly."  The strong one almost reconstructs the
  2634. ;;; grammar of C++; the weak one just figures anything id or curly on
  2635. ;;; the left begins a defun.  The constant "c++-match-header-strongly"
  2636. ;;; determines which to use; the default is the weak one.
  2637.  
  2638. (defvar c++-match-header-strongly nil
  2639.   "*If nil, use `c++-defun-header-weak' to identify beginning of definitions,
  2640. if non-nil, use `c++-defun-header-strong'.")
  2641.  
  2642. (defvar c++-defun-header-strong-struct-equivs
  2643.   "\\(class\\|struct\\|union\\|enum\\)"
  2644.   "Regexp to match names of structure declaration blocks in C++")
  2645.  
  2646. (defconst c++-defun-header-strong
  2647.   (let*
  2648.       (; valid identifiers
  2649.        ;; There's a real weirdness here -- if I switch the below
  2650.        (id "\\(\\w\\|_\\)+")
  2651.        ;; to be
  2652.        ;; (id "\\(_\\|\\w\\)+")
  2653.        ;; things no longer work right.  Try it and see!
  2654.  
  2655.        ; overloadable operators
  2656.        (op-sym1
  2657.      "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?")
  2658.        (op-sym2
  2659.      "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]")     
  2660.        (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)"))
  2661.        ; whitespace
  2662.        (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*")
  2663.        (c-comment (concat "/\\*" middle "\\*+/"))
  2664.        (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)"))
  2665.        (wh-opt (concat wh "*"))
  2666.        (wh-nec (concat wh "+"))
  2667.        (oper (concat "\\(" "operator" "\\("
  2668.              wh-opt op-sym "\\|" wh-nec id "\\)" "\\)"))
  2669.        (dcl-list "([^():]*)")
  2670.        (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)"))
  2671.        (inits
  2672.      (concat "\\(:"
  2673.          "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*"
  2674.          wh-opt id "(.*)" wh-opt "{"
  2675.          "\\|" wh-opt "{\\)"))
  2676.        (type-name (concat
  2677.             "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?"
  2678.             id))
  2679.        (type (concat "\\(const" wh-nec "\\)?"
  2680.              "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|"
  2681.              type-name wh-opt "&" "\\)"))
  2682.        (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)")
  2683.        (modifiers (concat "\\(" modifier wh-nec "\\)*"))
  2684.        (func-header
  2685.      ;;     type               arg-dcl
  2686.      (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits))
  2687.        (inherit (concat "\\(:" wh-opt "\\(public\\|protected\\|private\\)?"
  2688.             wh-nec id "\\)"))
  2689.        (cs-header (concat
  2690.             c++-defun-header-strong-struct-equivs
  2691.             wh-nec id wh-opt inherit "?" wh-opt "{")))
  2692.     (concat "^\\(" func-header "\\|" cs-header "\\)"))
  2693.   "Strongly-defined regexp to match beginning of structure or
  2694. function definition.")
  2695.  
  2696.  
  2697. ;; This part has to do with recognizing defuns.
  2698.  
  2699. ;; The weak convention we will use is that a defun begins any time
  2700. ;; there is a left curly brace, or some identifier on the left margin,
  2701. ;; followed by a left curly somewhere on the line.  (This will also
  2702. ;; incorrectly match some continued strings, but this is after all
  2703. ;; just a weak heuristic.)  Suggestions for improvement (short of the
  2704. ;; strong scheme shown above) are welcomed.
  2705.  
  2706. (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{"
  2707.   "Weakly-defined regexp to match beginning of structure or function
  2708. definition.")
  2709.  
  2710.  
  2711. (defun c++-beginning-of-defun (&optional arg)
  2712.   "Find the beginning of the C++ function or class."
  2713.   (interactive "p")
  2714.   (if (not arg) (setq arg 1))
  2715.   (let ((c++-defun-header (if c++-match-header-strongly
  2716.                   c++-defun-header-strong
  2717.                 c++-defun-header-weak)))
  2718.     (cond
  2719.      ((or (= arg 0) (and (> arg 0) (bobp))) nil)
  2720.      ((and (not (looking-at c++-defun-header))
  2721.        (let ((curr-pos (point))
  2722.          (open-pos (if (search-forward "{" nil 'move)
  2723.                    (point)))
  2724.          (beg-pos
  2725.           (if (re-search-backward c++-defun-header nil 'move)
  2726.               (match-beginning 0))))
  2727.          (if (and open-pos beg-pos
  2728.               (< beg-pos curr-pos)
  2729.               (> open-pos curr-pos))
  2730.          (progn
  2731.            (goto-char beg-pos)
  2732.            (if (= arg 1) t nil));; Are we done?
  2733.            (goto-char curr-pos)
  2734.            nil))))
  2735.      (t
  2736.       (if (and (looking-at c++-defun-header) (not (bobp)))
  2737.       (forward-char (if (< arg 0) 1 -1)))
  2738.       (and (re-search-backward c++-defun-header nil 'move (or arg 1))
  2739.        (goto-char (match-beginning 0)))))))
  2740.  
  2741.  
  2742. (defun c++-end-of-defun (arg)
  2743.   "Find the end of the C++ function or class."
  2744.   (interactive "p")
  2745.   (let ((c++-defun-header (if c++-match-header-strongly
  2746.                   c++-defun-header-strong
  2747.                 c++-defun-header-weak))
  2748.     (parse-sexp-ignore-comments t))
  2749.     (if (and (eobp) (> arg 0))
  2750.     nil
  2751.       (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1))
  2752.       (let ((pos (point)))
  2753.     (c++-beginning-of-defun 
  2754.       (if (< arg 0)
  2755.           (- (- arg (if (eobp) 0 1)))
  2756.         arg))
  2757.     (if (and (< arg 0) (bobp))
  2758.         t
  2759.       (if (re-search-forward c++-defun-header nil 'move)
  2760.           (progn (forward-char -1)
  2761.              (forward-sexp)
  2762.              (beginning-of-line 2)))
  2763.       (if (and (= pos (point)) 
  2764.            (re-search-forward c++-defun-header nil 'move))
  2765.           (c++-end-of-defun 1))))
  2766.       t)))
  2767.  
  2768. (defun c++-indent-defun ()
  2769.   "Indents the current function def, struct or class declaration."
  2770.   (interactive)
  2771.   (let ((restore (point)))
  2772.     (c++-end-of-defun 1)
  2773.     (beginning-of-line 1)
  2774.     (let ((end (point-marker)))
  2775.       (c++-beginning-of-defun)
  2776.       (while (and (< (point) end))
  2777.     (c++-indent-line)
  2778.     (forward-line 1)
  2779.     (beginning-of-line 1))
  2780.       (set-marker end nil))
  2781.     (goto-char restore)))
  2782.  
  2783.  
  2784. ;; ======================================================================
  2785. ;; defuns for submitting bug reports
  2786. ;; ======================================================================
  2787. (defconst c++-version "2.353"
  2788.   "c++-mode version number.")
  2789. (defconst c++-mode-help-address "c++-mode-help@anthem.nlm.nih.gov"
  2790.   "Address accepting submission of bug reports.")
  2791.  
  2792. (defun c++-version ()
  2793.   "Echo the current version of c++-mode."
  2794.   (interactive)
  2795.   (message "Using c++-mode.el %s" c++-version))
  2796.  
  2797. (defun c++-submit-bug-report ()
  2798.   "Submit via mail a bug report on c++-mode."
  2799.   (interactive)
  2800.   (require 'reporter)
  2801.   (and
  2802.    (y-or-n-p "Do you want to submit a report on c++-mode? ")
  2803.    (reporter-submit-bug-report
  2804.     c++-mode-help-address
  2805.     (concat "c++-mode.el " c++-version " (editing "
  2806.         (if (eq major-mode 'c++-mode) "C++" "C")
  2807.         " code)")
  2808.     (list
  2809.      'c++-emacs-features
  2810.      'c++-C-block-comments-indent-p
  2811.      'c++-access-specifier-offset
  2812.      'c++-always-arglist-indent-p
  2813.      'c++-auto-hungry-initial-state
  2814.      'c++-auto-hungry-toggle
  2815.      'c++-auto-newline
  2816.      'c++-backscan-limit
  2817.      'c++-block-close-brace-offset
  2818.      'c++-cleanup-list
  2819.      'c++-comment-only-line-offset
  2820.      'c++-continued-member-init-offset
  2821.      'c++-default-macroize-column
  2822.      'c++-defun-header-strong-struct-equivs
  2823.      'c++-delete-function
  2824.      'c++-electric-pound-behavior
  2825.      'c++-empty-arglist-indent
  2826.      'c++-friend-offset
  2827.      'c++-hanging-braces
  2828.      'c++-hanging-member-init-colon
  2829.      'c++-hungry-delete-key
  2830.      'c++-match-header-strongly
  2831.      'c++-member-init-indent
  2832.      'c++-paren-as-block-close-p
  2833.      'c++-relative-offset-p
  2834.      'c++-tab-always-indent
  2835.      'c++-untame-characters
  2836.      'c-argdecl-indent
  2837.      'c-brace-imaginary-offset
  2838.      'c-brace-offset
  2839.      'c-continued-brace-offset
  2840.      'c-continued-statement-offset
  2841.      'c-indent-level
  2842.      'c-label-offset
  2843.      'tab-width
  2844.      )
  2845.     (function
  2846.      (lambda ()
  2847.        (insert
  2848.     (if c++-special-indent-hook
  2849.         (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
  2850.             "c++-special-indent-hook is set to '"
  2851.             (format "%s" c++-special-indent-hook)
  2852.             ".\nPerhaps this is your problem?\n"
  2853.             "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
  2854.       "\n")
  2855.     )))
  2856.     )))
  2857.  
  2858.  
  2859. ;; this is sometimes useful
  2860. (provide 'c++-mode)
  2861.  
  2862. ;;; cplus-md1.el ends here
  2863.  
  2864.